Skip to content
Browse files

added support for long-click to launch image in separate activity w/ …

…zoom, pan
  • Loading branch information...
1 parent fc9d30d commit 5a2a07d940467e88ae120cd96b87e8b7296eec94 @commonsguy committed
View
3 AndroidManifest.xml
@@ -9,6 +9,8 @@
android:minSdkVersion="8"
android:targetSdkVersion="11"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+
<application>
<activity android:name="EmPubActivity">
<intent-filter>
@@ -18,6 +20,7 @@
</intent-filter>
</activity>
<activity android:name="SimpleContentActivity"/>
+ <activity android:name="ImageActivity"/>
<activity android:name="Preferences"/>
<receiver
View
2 demo/AndroidManifest.xml
@@ -13,6 +13,7 @@
android:normalScreens="true"
android:smallScreens="false"
android:xlargeScreens="true"/>
+
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
@@ -29,6 +30,7 @@
</intent-filter>
</activity>
<activity android:name="com.commonsware.empub.SimpleContentActivity"/>
+ <activity android:name="com.commonsware.empub.ImageActivity"/>
<activity android:name="com.commonsware.empub.Preferences"/>
<receiver
View
2 res/layout/empub_image.xml
@@ -1,4 +1,4 @@
-<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.example.touch.TouchImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
View
35 src/com/commonsware/empub/ChapterFragment.java
@@ -12,13 +12,19 @@
package com.commonsware.empub;
import android.annotation.TargetApi;
+import android.content.Intent;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnLongClickListener;
import android.webkit.WebSettings;
import android.webkit.WebView;
+import android.webkit.WebView.HitTestResult;
import android.webkit.WebViewClient;
-public class ChapterFragment extends AbstractContentFragment {
+public class ChapterFragment extends AbstractContentFragment implements
+ OnLongClickListener {
private static final String KEY_FILE="file";
private int zoomLevel=100;
@@ -37,10 +43,10 @@ protected static ChapterFragment newInstance(String file) {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- // following required due to bug
// http://code.google.com/p/android/issues/detail?id=3440
getWebView().getSettings().setBuiltInZoomControls(false);
getWebView().setWebViewClient(new ChapterClient());
+ getWebView().setOnLongClickListener(this);
updateZoom();
final String anchor=
@@ -57,15 +63,30 @@ public void run() {
}, 1000);
}
}
-
+
@Override
public void onResume() {
super.onResume();
-
+
setZoom(((EmPubActivity)getActivity()).getZoom());
}
@Override
+ public boolean onLongClick(View v) {
+ HitTestResult hit=getWebView().getHitTestResult();
+
+ if (hit.getType() == HitTestResult.IMAGE_TYPE
+ || hit.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
+ Intent i=new Intent(getActivity(), ImageActivity.class);
+
+ i.putExtra(ImageActivity.EXTRA_FILE, Uri.parse(hit.getExtra()).getLastPathSegment());
+ startActivity(i);
+ }
+
+ return false;
+ }
+
+ @Override
String getPage() {
return("file:///android_asset/book/" + getArguments().getString(KEY_FILE));
}
@@ -84,12 +105,12 @@ protected void jumpTo(String anchor) {
void setZoom(int zoomLevel) {
this.zoomLevel=zoomLevel;
-
- if (getWebView()!=null) {
+
+ if (getWebView() != null) {
updateZoom();
}
}
-
+
@TargetApi(14)
private void updateZoom() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
View
33 src/com/commonsware/empub/ImageActivity.java
@@ -0,0 +1,33 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
+public class ImageActivity extends SherlockFragmentActivity {
+ public static final String EXTRA_FILE="file";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String file=getIntent().getStringExtra(EXTRA_FILE);
+ Fragment f=ImageFragment.newInstance(file, null);
+
+ getSupportFragmentManager().beginTransaction()
+ .add(android.R.id.content, f).commit();
+ }
+ }
+}
View
235 src/com/example/touch/TouchImageView.java
@@ -0,0 +1,235 @@
+/*
+ * TouchImageView.java
+ * By: Michael Ortiz
+ * Updated By: Patrick Lackemacher
+ * Updated By: Babay88
+ * -------------------
+ * Extends Android ImageView to include pinch zooming and panning.
+ */
+
+package com.example.touch;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.View;
+import android.widget.ImageView;
+
+public class TouchImageView extends ImageView {
+
+ Matrix matrix;
+
+ // We can be in one of these 3 states
+ static final int NONE = 0;
+ static final int DRAG = 1;
+ static final int ZOOM = 2;
+ int mode = NONE;
+
+ // Remember some things for zooming
+ PointF last = new PointF();
+ PointF start = new PointF();
+ float minScale = 1f;
+ float maxScale = 3f;
+ float[] m;
+
+
+ int viewWidth, viewHeight;
+ static final int CLICK = 3;
+ float saveScale = 1f;
+ protected float origWidth, origHeight;
+ int oldMeasuredWidth, oldMeasuredHeight;
+
+
+ ScaleGestureDetector mScaleDetector;
+
+ Context context;
+
+ public TouchImageView(Context context) {
+ super(context);
+ sharedConstructing(context);
+ }
+
+ public TouchImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ sharedConstructing(context);
+ }
+
+ private void sharedConstructing(Context context) {
+ super.setClickable(true);
+ this.context = context;
+ mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+ matrix = new Matrix();
+ m = new float[9];
+ setImageMatrix(matrix);
+ setScaleType(ScaleType.MATRIX);
+
+ setOnTouchListener(new OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ mScaleDetector.onTouchEvent(event);
+ PointF curr = new PointF(event.getX(), event.getY());
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ last.set(curr);
+ start.set(last);
+ mode = DRAG;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (mode == DRAG) {
+ float deltaX = curr.x - last.x;
+ float deltaY = curr.y - last.y;
+ float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
+ float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
+ matrix.postTranslate(fixTransX, fixTransY);
+ fixTrans();
+ last.set(curr.x, curr.y);
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ mode = NONE;
+ int xDiff = (int) Math.abs(curr.x - start.x);
+ int yDiff = (int) Math.abs(curr.y - start.y);
+ if (xDiff < CLICK && yDiff < CLICK)
+ performClick();
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ mode = NONE;
+ break;
+ }
+
+ setImageMatrix(matrix);
+ invalidate();
+ return true; // indicate event was handled
+ }
+
+ });
+ }
+
+ public void setMaxZoom(float x) {
+ maxScale = x;
+ }
+
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ mode = ZOOM;
+ return true;
+ }
+
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ float mScaleFactor = detector.getScaleFactor();
+ float origScale = saveScale;
+ saveScale *= mScaleFactor;
+ if (saveScale > maxScale) {
+ saveScale = maxScale;
+ mScaleFactor = maxScale / origScale;
+ } else if (saveScale < minScale) {
+ saveScale = minScale;
+ mScaleFactor = minScale / origScale;
+ }
+
+ if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
+ matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
+ else
+ matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
+
+ fixTrans();
+ return true;
+ }
+ }
+
+ void fixTrans() {
+ matrix.getValues(m);
+ float transX = m[Matrix.MTRANS_X];
+ float transY = m[Matrix.MTRANS_Y];
+
+ float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
+ float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);
+
+ if (fixTransX != 0 || fixTransY != 0)
+ matrix.postTranslate(fixTransX, fixTransY);
+ }
+
+ float getFixTrans(float trans, float viewSize, float contentSize) {
+ float minTrans, maxTrans;
+
+ if (contentSize <= viewSize) {
+ minTrans = 0;
+ maxTrans = viewSize - contentSize;
+ } else {
+ minTrans = viewSize - contentSize;
+ maxTrans = 0;
+ }
+
+ if (trans < minTrans)
+ return -trans + minTrans;
+ if (trans > maxTrans)
+ return -trans + maxTrans;
+ return 0;
+ }
+
+ float getFixDragTrans(float delta, float viewSize, float contentSize) {
+ if (contentSize <= viewSize) {
+ return 0;
+ }
+ return delta;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ viewWidth = MeasureSpec.getSize(widthMeasureSpec);
+ viewHeight = MeasureSpec.getSize(heightMeasureSpec);
+
+ //
+ // Rescales image on rotation
+ //
+ if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
+ || viewWidth == 0 || viewHeight == 0)
+ return;
+ oldMeasuredHeight = viewHeight;
+ oldMeasuredWidth = viewWidth;
+
+ if (saveScale == 1) {
+ //Fit to screen.
+ float scale;
+
+ Drawable drawable = getDrawable();
+ if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
+ return;
+ int bmWidth = drawable.getIntrinsicWidth();
+ int bmHeight = drawable.getIntrinsicHeight();
+
+ Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
+
+ float scaleX = (float) viewWidth / (float) bmWidth;
+ float scaleY = (float) viewHeight / (float) bmHeight;
+ scale = Math.min(scaleX, scaleY);
+ matrix.setScale(scale, scale);
+
+ // Center the image
+ float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
+ float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
+ redundantYSpace /= (float) 2;
+ redundantXSpace /= (float) 2;
+
+ matrix.postTranslate(redundantXSpace, redundantYSpace);
+
+ origWidth = viewWidth - 2 * redundantXSpace;
+ origHeight = viewHeight - 2 * redundantYSpace;
+ setImageMatrix(matrix);
+ }
+ fixTrans();
+ }
+}

0 comments on commit 5a2a07d

Please sign in to comment.
Something went wrong with that request. Please try again.