package com.librelio.library.ui.productdetail; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import android.annotation.SuppressLint; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.Toast; import com.librelio.library.ui.BaseNivealesFragment; import com.librelio.library.ui.NivealesApplication; import com.librelio.library.ui.NivealesApplication.ProductDetailConstants; import com.librelio.library.ui.popup.ActionItem; import com.librelio.library.ui.popup.ImageZoomPopup; import com.librelio.library.utils.db.DBHelper; public class ProductDetailFragment extends BaseNivealesFragment { private static final String ZOOM_TOUCHMOVE = "zoom://touchmove/"; private static final String ZOOM_FINISH = "zoom://finish"; private static final String ZOOM_TOUCHSTART = "zoom://touchstart"; private static final String ZOOM_TOUCHEND = "zoom://touchend"; View rootView; String htmlBasePage; // text from assets html page to customize String customizedHTMLPage; // page after customization DBHelper helper; private String productId; Cursor productCursor; String pic; private int productDetailLayout; private int webViewId; private int favoriteId; private int shareId; ShareProductListener listener; private String[] columnKeys; private String[] htmlKeys; private ImageButton mPrevButton; private WebView webView; private ImageButton mNextButton; // private ImageView mProductImage; private ImageZoomPopup mProductImagePopup; private int bitmapWidth; private int bitmapHeight; private Bitmap mHiResBitmap; private int webPageStringResourceId; protected float downX; protected float downY; protected boolean isZoomStarted = false; private ArrayList<ActionItem> mActionItems = new ArrayList<ActionItem>(); private CheckBox mFavoriteCheckBox; private int[] mZoomCoords; private void init(int productDetailLayout, int webViewId, int webPageStringResourceId, String[] columnKeys, String[] htmlKeys, int favoriteCheckboxId, int shareButtonId) { this.helper = NivealesApplication.getDBHelper(); this.productDetailLayout = productDetailLayout; this.webViewId = webViewId; this.favoriteId = favoriteCheckboxId; this.shareId = shareButtonId; this.htmlKeys = htmlKeys; this.columnKeys = columnKeys; this.webPageStringResourceId = webPageStringResourceId; } public void setProductCursor(Cursor c) { this.productCursor = c; } public void setOnShareProductListener(ShareProductListener l) { this.listener = l; } public String readHTML() { BufferedInputStream bin; try { bin = new BufferedInputStream(getActivity().getAssets().open( getActivity().getString(webPageStringResourceId))); InputStreamReader in = new InputStreamReader(bin, "UTF-8"); StringWriter w = new StringWriter(); char[] buffer = new char[1024]; int count = 0; while ((count = in.read(buffer, 0, 1024)) > 0) { w.write(buffer, 0, count); } in.close(); w.close(); return w.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } String getHTMLPage(Cursor c) { productId = c.getString(c.getColumnIndexOrThrow("id_modele")); String htmlString = new String(htmlBasePage); for (int i = 0; i < columnKeys.length; i++) { int columnIndex = c.getColumnIndex(columnKeys[i]); if (columnIndex != -1) { String value = c.getString(columnIndex); if (htmlKeys[i].startsWith("%icone") && !value.equals("")) { value = "<img src=\"" + NivealesApplication.ASSETS_URI + value + "\"/>"; } else { if (value.endsWith("png") || value.endsWith("jpg")) { // product image value = NivealesApplication.ASSETS_URI + value; } } htmlString = htmlString.replace(htmlKeys[i], value); } } Log.d("HTML", htmlString); return htmlString; } /* * private View.OnTouchListener mProductImageTouchListener = new * View.OnTouchListener() { private float mx; private float my; private * float deltaX, deltaY; int maxX = 0, maxY = 0; * * @Override public boolean onTouch(View pV, MotionEvent pEvent) { * * float curX, curY; * * switch (pEvent.getAction()) { * * case MotionEvent.ACTION_DOWN: mx = pEvent.getX(); my = pEvent.getY(); * deltaX = deltaY = 0; maxX = Math.abs(bitmapWidth - * mProductImage.getWidth()) / 2; maxY = Math.abs(bitmapHeight - * mProductImage.getHeight()) / 2; break; case MotionEvent.ACTION_MOVE: curX * = pEvent.getX(); curY = pEvent.getY(); deltaX = mx - curX; deltaY = my - * curY; mx = curX; my = curY; float scrollX = mProductImage.getScrollX(); * float scrollY = mProductImage.getScrollY(); if (scrollX + deltaX < -maxX) * scrollX = -maxX; else if (scrollX + deltaX > maxX) scrollX = maxX; else * scrollX += deltaX; * * if (scrollY + deltaY < -maxY) scrollY = -maxY; else if (scrollY + deltaY * > maxY) scrollY = maxY; else scrollY += deltaY; * * mProductImage.scrollTo((int) scrollX, (int) scrollY); break; case * MotionEvent.ACTION_UP: curX = pEvent.getX(); curY = pEvent.getY(); deltaX * = mx - curX; deltaY = my - curY; break; } * * return true; } }; */ public void loadProduct(Cursor c) { webView.loadDataWithBaseURL(NivealesApplication.ASSETS_URI, getHTMLPage(c), "text/html", "UTF-8", null); mFavoriteCheckBox.setChecked(helper.isFavorite(productId)); } @SuppressLint("SetJavaScriptEnabled") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { init(ProductDetailConstants.PRODUCT_DETAIL_LAYOUT, ProductDetailConstants.PRODUCT_DETAIL_WEBVIEW_VIEW_ID, ProductDetailConstants.PRODUCT_DETAIL_WEBPAGE_FILE_URI, ProductDetailConstants.PRODUCT_DETAIL_COLUMN_KEYS, ProductDetailConstants.PRODUCT_DETAIL_HTML_FILE_KEYS, ProductDetailConstants.PRODUCT_DETAIL_FAVORITE_CKECKBOX_VIEW_ID, ProductDetailConstants.PRODUCT_DETAIL_SHARE_BUTTON_VIEW_ID); rootView = inflater.inflate(productDetailLayout, container, false); htmlBasePage = readHTML(); webView = (WebView) rootView.findViewById(webViewId); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("zoom://")) { // view.loadDataWithBaseURL(Consts.ASSETS_URI, text, // "text/html", "UTF-8", null); showLargeImage(url); return true; } return false; } }); webView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View pV, MotionEvent pEvent) { if (isZoomStarted) { if(pEvent.getAction() == MotionEvent.ACTION_MOVE){ float density = getActivity().getResources() .getDisplayMetrics().density; float touchX = Math.round(pEvent.getX())/density; float touchY = Math.round(pEvent.getY())/density; if(touchX >= mZoomCoords[4] && touchY >= mZoomCoords[2] && touchX <= mZoomCoords[5] + mZoomCoords[4] && touchY <= mZoomCoords[3] + mZoomCoords[2]) { String zoomString = ZOOM_TOUCHMOVE+"?"+Math.round(touchX)+","+Math.round(touchY)+","+mZoomCoords[2]+","+mZoomCoords[3]+","+mZoomCoords[4]+","+mZoomCoords[5]; showLargeImage(zoomString); } } if(pEvent.getAction() == MotionEvent.ACTION_UP) { showLargeImage(ZOOM_FINISH); } return true; } return false; } }); ImageView shareButton = (ImageView) rootView.findViewById(shareId); shareButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { listener.onShareProduct(productCursor); } }); mFavoriteCheckBox = (CheckBox) rootView.findViewById(favoriteId); mFavoriteCheckBox .setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton pButtonView, boolean pIsChecked) { if (!pButtonView.isPressed()) return; if (pIsChecked) { helper.addFavorite(productId); } else { helper.deleteFavorite(productId); } } }); mPrevButton = (ImageButton) rootView .findViewById(NivealesApplication.ProductDetailConstants.PRODUCT_DETAIL_PREVBUTTON_VIEW_ID); mPrevButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View pV) { if (!productCursor.isFirst()) { productCursor.move(-1); // recycleImageViewBitmap(mProductImage); if(mProductImagePopup != null) mProductImagePopup.dismiss(); // loadImageBitmap(); loadProduct(productCursor); } } }); mNextButton = (ImageButton) rootView .findViewById(NivealesApplication.ProductDetailConstants.PRODUCTDETAIL_NEXTBUTTON_VIEW_ID); mNextButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View pV) { if (!productCursor.isLast()) { productCursor.move(1); // recycleImageViewBitmap(mProductImage); if(mProductImagePopup != null) mProductImagePopup.dismiss(); // loadImageBitmap(); loadProduct(productCursor); } } }); loadProduct(productCursor); return rootView; } protected void showLargeImage(String pUrl) { if (pUrl.startsWith(ZOOM_TOUCHSTART)) { String[] coordStr = pUrl.split("\\?")[1].split(","); int[] coords = new int[coordStr.length]; for (int i = 0; i < coords.length; i++) coords[i] = Integer.valueOf(coordStr[i]); this.mZoomCoords = coords; mProductImagePopup = new ImageZoomPopup(webView, coords) { @Override public void onDismiss() { super.onDismiss(); isZoomStarted = false; } }; mProductImagePopup.setBackgroundDrawable(new ColorDrawable( Color.WHITE)); mProductImagePopup.setImageBitmap(getProductBitmap()); mProductImagePopup.show(); isZoomStarted = true; DownloadHiResTask task = new DownloadHiResTask(); task.execute(productCursor.getString(productCursor .getColumnIndexOrThrow("imgHR"))); } if (pUrl.startsWith(ZOOM_FINISH) || pUrl.startsWith(ZOOM_TOUCHEND)) { // this.mProductImageGoneHandler.removeCallbacks(mProductImageGoneRunnable); // mProductImage.setVisibility(View.GONE); mProductImagePopup.dismiss(); isZoomStarted = false; } // if(pUrl.startsWith(ZOOM_TOUCHEND)) { // mProductImage.setVisibility(View.GONE); // isZoomStarted = false; // } if (pUrl.startsWith(ZOOM_TOUCHMOVE)) { if (isZoomStarted) { String[] coordStr = pUrl.split("\\?")[1].split(","); int[] coords = new int[coordStr.length]; for (int i = 0; i < coords.length; i++) coords[i] = Integer.valueOf(coordStr[i]); mProductImagePopup.scroll(coords); } } Log.d("zoom", pUrl); Log.d("DPI", String.valueOf(getActivity().getResources() .getDisplayMetrics().density)); } public Bitmap getProductBitmap() { try { pic = productCursor.getString(productCursor .getColumnIndexOrThrow("imgLR")); Bitmap b = BitmapFactory.decodeStream(getActivity().getAssets() .open(pic)); this.bitmapWidth = b.getWidth(); this.bitmapHeight = b.getHeight(); return b; } catch (IOException e) { e.printStackTrace(); } return null; } public void recycleImageViewBitmap(ImageView i) { if (i != null) { Drawable d = i.getDrawable(); if (d instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) d; bd.getBitmap().recycle(); } } mHiResBitmap = null; } public void onShareStarted() { } public interface ShareProductListener { public void onShareProduct(Cursor productCursor); } public Cursor getCursor() { return productCursor; } public class DownloadHiResTask extends AsyncTask<String, Void, Bitmap> { String lastError = "Unknown Error"; @Override protected Bitmap doInBackground(String... pParams) { try { Uri uri = Uri.parse(pParams[0]); String fileName = uri.getLastPathSegment(); URL url = new URL(pParams[0]); HttpURLConnection urlConnection = (HttpURLConnection) url .openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setDoOutput(true); urlConnection.connect(); File tempFile = new File(getActivity().getCacheDir() .getAbsolutePath() + "/" + fileName); int totalSize = urlConnection.getContentLength(); int downloaded = 0; if (tempFile.exists()) { // check the existing file size if (tempFile.length() == totalSize) { Bitmap b = BitmapFactory .decodeStream(new FileInputStream(tempFile)); return b; } else { tempFile.delete(); } } tempFile.createNewFile(); FileOutputStream fos = new FileOutputStream(tempFile); InputStream is = urlConnection.getInputStream(); byte[] buf = new byte[1024]; int count = 0; while ((count = is.read(buf)) > 0) { fos.write(buf, 0, count); downloaded += count; } fos.close(); is.close(); Bitmap b = BitmapFactory.decodeStream(new FileInputStream( tempFile)); return b; } catch (MalformedURLException e) { e.printStackTrace(); lastError = e.getMessage(); } catch (IOException e) { e.printStackTrace(); lastError = "Network error"; } return null; } @Override protected void onPostExecute(Bitmap result) { if (result != null) { if (result.getWidth() > 2048) { float scale = 2048f / (float) result.getWidth(); float height = (float) result.getHeight(); height = height * scale; Bitmap scaledBitmap = Bitmap.createScaledBitmap(result, 2048, Math.round(height), true); result.recycle(); result = scaledBitmap; } bitmapWidth = result.getWidth(); bitmapHeight = result.getHeight(); mHiResBitmap = result; if (mProductImagePopup != null) { // mProductImage.setScaleType(ScaleType.CENTER); mProductImagePopup.setImageBitmap(mHiResBitmap); } } else { Toast.makeText(getActivity(), lastError, Toast.LENGTH_SHORT) .show(); } } }; }