From 12f64363c82274587ebb07774de1a872f54ca3ae Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 3 Feb 2019 23:53:57 +0300 Subject: android support libraries -> androidx use photoview instead of imageviewtouch (included because of TOP_CROP missing) remove obsolete/unused code --- org.fox.ttcomics/build.gradle | 11 +- org.fox.ttcomics/org.fox.ttcomics.iml | 87 +-- org.fox.ttcomics/src/main/AndroidManifest.xml | 6 +- .../com/github/chrisbanes/photoview/Compat.java | 39 + .../photoview/CustomGestureDetector.java | 205 +++++ .../chrisbanes/photoview/OnGestureListener.java | 27 + .../photoview/OnMatrixChangedListener.java | 18 + .../photoview/OnOutsidePhotoTapListener.java | 14 + .../chrisbanes/photoview/OnPhotoTapListener.java | 22 + .../photoview/OnScaleChangedListener.java | 17 + .../photoview/OnSingleFlingListener.java | 21 + .../chrisbanes/photoview/OnViewDragListener.java | 16 + .../chrisbanes/photoview/OnViewTapListener.java | 16 + .../com/github/chrisbanes/photoview/PhotoView.java | 256 +++++++ .../chrisbanes/photoview/PhotoViewAttacher.java | 822 +++++++++++++++++++++ .../java/com/github/chrisbanes/photoview/Util.java | 37 + .../android/library/imagezoom/ImageViewTouch.java | 268 ------- .../library/imagezoom/ImageViewTouchBase.java | 512 ------------- .../android/library/imagezoom/easing/Cubic.java | 20 - .../android/library/imagezoom/easing/Easing.java | 10 - .../imagezoom/graphics/FastBitmapDrawable.java | 84 --- .../imagezoom/graphics/IBitmapDrawable.java | 14 - .../library/imagezoom/utils/IDisposable.java | 6 - .../main/java/org/fox/ttcomics2/Application.java | 4 +- .../main/java/org/fox/ttcomics2/ComicFragment.java | 180 +---- .../java/org/fox/ttcomics2/ComicListFragment.java | 6 +- .../main/java/org/fox/ttcomics2/ComicPager.java | 25 +- .../java/org/fox/ttcomics2/CommonActivity.java | 7 +- .../main/java/org/fox/ttcomics2/MainActivity.java | 14 +- .../org/fox/ttcomics2/PreferencesActivity.java | 3 +- .../java/org/fox/ttcomics2/StateSavedFragment.java | 3 +- .../java/org/fox/ttcomics2/ViewComicActivity.java | 6 +- .../fox/ttcomics2/utils/CacheCleanupService.java | 3 +- .../fox/ttcomics2/utils/CompatListActivity.java | 33 - .../java/org/fox/ttcomics2/utils/IVTViewPager.java | 39 - .../src/main/res/layout/activity_main.xml | 6 +- .../src/main/res/layout/comics_grid_row.xml | 4 +- .../src/main/res/layout/fragment_comic.xml | 3 +- .../src/main/res/layout/fragment_comics_grid.xml | 4 +- .../src/main/res/layout/fragment_comics_pager.xml | 2 +- org.fox.ttcomics/src/main/res/layout/toolbar.xml | 2 +- 41 files changed, 1647 insertions(+), 1225 deletions(-) create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Compat.java create mode 100755 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/CustomGestureDetector.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnGestureListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnMatrixChangedListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnOutsidePhotoTapListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnPhotoTapListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnScaleChangedListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnSingleFlingListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewDragListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewTapListener.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoView.java create mode 100755 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoViewAttacher.java create mode 100644 org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Util.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java delete mode 100755 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Cubic.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Easing.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/FastBitmapDrawable.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/IBitmapDrawable.java delete mode 100644 org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/utils/IDisposable.java delete mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CompatListActivity.java delete mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/IVTViewPager.java mode change 100644 => 100755 org.fox.ttcomics/src/main/res/layout/fragment_comic.xml mode change 100644 => 100755 org.fox.ttcomics/src/main/res/layout/fragment_comics_grid.xml mode change 100644 => 100755 org.fox.ttcomics/src/main/res/layout/toolbar.xml (limited to 'org.fox.ttcomics') diff --git a/org.fox.ttcomics/build.gradle b/org.fox.ttcomics/build.gradle index 8d2814a..9e52a1c 100755 --- a/org.fox.ttcomics/build.gradle +++ b/org.fox.ttcomics/build.gradle @@ -47,10 +47,9 @@ android { } dependencies { - implementation 'com.android.support:support-v4:28.0.0' - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support:cardview-v7:28.0.0' - implementation 'com.android.support:design:28.0.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.appcompat:appcompat:1.1.0-alpha01' + implementation 'com.google.android.material:material:1.1.0-alpha03' implementation 'com.shamanland:fab:0.0.8' implementation 'jp.co.recruit_mp:android-HeaderFooterGridView:0.2.4' implementation 'com.github.bumptech.glide:glide:3.8.0' @@ -61,8 +60,8 @@ dependencies { compileOnly 'frankiesardo:icepick-processor:3.2.0' implementation 'com.github.livefront:bridge:v1.1.2' annotationProcessor 'frankiesardo:icepick-processor:3.2.0' - implementation 'com.google.android.gms:play-services-base:15.0.1' - implementation 'com.google.android.gms:play-services-auth:15.0.1' + implementation 'com.google.android.gms:play-services-base:16.1.0' + implementation 'com.google.android.gms:play-services-auth:16.0.1' implementation files('libs/nineoldandroids-2.4.0.jar') implementation 'com.gu:option:1.3' implementation 'net.rdrei.android.dirchooser:library:3.2@aar' diff --git a/org.fox.ttcomics/org.fox.ttcomics.iml b/org.fox.ttcomics/org.fox.ttcomics.iml index 394c135..4d82cb9 100755 --- a/org.fox.ttcomics/org.fox.ttcomics.iml +++ b/org.fox.ttcomics/org.fox.ttcomics.iml @@ -125,69 +125,72 @@ - - - - - - - - + + + + + + + - + + + - - + - + - + + + + - - - - - - - - + + + + - - + + + + - + + + + - - + - + - + + + + - - - + + + + + + - - + - + - - - - - - - - + + + \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/AndroidManifest.xml b/org.fox.ttcomics/src/main/AndroidManifest.xml index 4342ef8..2ee0e0f 100755 --- a/org.fox.ttcomics/src/main/AndroidManifest.xml +++ b/org.fox.ttcomics/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="89" + android:versionName="1.47" > @@ -70,7 +70,7 @@ android:exported="false"/> diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Compat.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Compat.java new file mode 100644 index 0000000..d33c31c --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Compat.java @@ -0,0 +1,39 @@ +/* + Copyright 2011, 2012 Chris Banes. + + 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.github.chrisbanes.photoview; + +import android.annotation.TargetApi; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.view.View; + +class Compat { + + private static final int SIXTY_FPS_INTERVAL = 1000 / 60; + + public static void postOnAnimation(View view, Runnable runnable) { + if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { + postOnAnimationJellyBean(view, runnable); + } else { + view.postDelayed(runnable, SIXTY_FPS_INTERVAL); + } + } + + @TargetApi(16) + private static void postOnAnimationJellyBean(View view, Runnable runnable) { + view.postOnAnimation(runnable); + } +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/CustomGestureDetector.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/CustomGestureDetector.java new file mode 100755 index 0000000..822754f --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/CustomGestureDetector.java @@ -0,0 +1,205 @@ +/* + Copyright 2011, 2012 Chris Banes. +

+ 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.github.chrisbanes.photoview; + +import android.content.Context; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.VelocityTracker; +import android.view.ViewConfiguration; + +/** + * Does a whole lot of gesture detecting. + */ +class CustomGestureDetector { + + private static final int INVALID_POINTER_ID = -1; + + private int mActivePointerId = INVALID_POINTER_ID; + private int mActivePointerIndex = 0; + private final ScaleGestureDetector mDetector; + + private VelocityTracker mVelocityTracker; + private boolean mIsDragging; + private float mLastTouchX; + private float mLastTouchY; + private final float mTouchSlop; + private final float mMinimumVelocity; + private OnGestureListener mListener; + + CustomGestureDetector(Context context, OnGestureListener listener) { + final ViewConfiguration configuration = ViewConfiguration + .get(context); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mTouchSlop = configuration.getScaledTouchSlop(); + + mListener = listener; + ScaleGestureDetector.OnScaleGestureListener mScaleListener = new ScaleGestureDetector.OnScaleGestureListener() { + + @Override + public boolean onScale(ScaleGestureDetector detector) { + float scaleFactor = detector.getScaleFactor(); + + if (Float.isNaN(scaleFactor) || Float.isInfinite(scaleFactor)) + return false; + + if (scaleFactor >= 0) { + mListener.onScale(scaleFactor, + detector.getFocusX(), detector.getFocusY()); + } + return true; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + // NO-OP + } + }; + mDetector = new ScaleGestureDetector(context, mScaleListener); + } + + private float getActiveX(MotionEvent ev) { + try { + return ev.getX(mActivePointerIndex); + } catch (Exception e) { + return ev.getX(); + } + } + + private float getActiveY(MotionEvent ev) { + try { + return ev.getY(mActivePointerIndex); + } catch (Exception e) { + return ev.getY(); + } + } + + public boolean isScaling() { + return mDetector.isInProgress(); + } + + public boolean isDragging() { + return mIsDragging; + } + + public boolean onTouchEvent(MotionEvent ev) { + try { + mDetector.onTouchEvent(ev); + return processTouchEvent(ev); + } catch (IllegalArgumentException e) { + // Fix for support lib bug, happening when onDestroy is called + return true; + } + } + + private boolean processTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = ev.getPointerId(0); + + mVelocityTracker = VelocityTracker.obtain(); + if (null != mVelocityTracker) { + mVelocityTracker.addMovement(ev); + } + + mLastTouchX = getActiveX(ev); + mLastTouchY = getActiveY(ev); + mIsDragging = false; + break; + case MotionEvent.ACTION_MOVE: + final float x = getActiveX(ev); + final float y = getActiveY(ev); + final float dx = x - mLastTouchX, dy = y - mLastTouchY; + + if (!mIsDragging) { + // Use Pythagoras to see if drag length is larger than + // touch slop + mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop; + } + + if (mIsDragging) { + mListener.onDrag(dx, dy); + mLastTouchX = x; + mLastTouchY = y; + + if (null != mVelocityTracker) { + mVelocityTracker.addMovement(ev); + } + } + break; + case MotionEvent.ACTION_CANCEL: + mActivePointerId = INVALID_POINTER_ID; + // Recycle Velocity Tracker + if (null != mVelocityTracker) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; + case MotionEvent.ACTION_UP: + mActivePointerId = INVALID_POINTER_ID; + if (mIsDragging) { + if (null != mVelocityTracker) { + mLastTouchX = getActiveX(ev); + mLastTouchY = getActiveY(ev); + + // Compute velocity within the last 1000ms + mVelocityTracker.addMovement(ev); + mVelocityTracker.computeCurrentVelocity(1000); + + final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker + .getYVelocity(); + + // If the velocity is greater than minVelocity, call + // listener + if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) { + mListener.onFling(mLastTouchX, mLastTouchY, -vX, + -vY); + } + } + } + + // Recycle Velocity Tracker + if (null != mVelocityTracker) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; + case MotionEvent.ACTION_POINTER_UP: + final int pointerIndex = Util.getPointerIndex(ev.getAction()); + final int pointerId = ev.getPointerId(pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = ev.getPointerId(newPointerIndex); + mLastTouchX = ev.getX(newPointerIndex); + mLastTouchY = ev.getY(newPointerIndex); + } + break; + } + + mActivePointerIndex = ev + .findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId + : 0); + return true; + } +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnGestureListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnGestureListener.java new file mode 100644 index 0000000..f7722af --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnGestureListener.java @@ -0,0 +1,27 @@ +/* + Copyright 2011, 2012 Chris Banes. + + 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.github.chrisbanes.photoview; + +interface OnGestureListener { + + void onDrag(float dx, float dy); + + void onFling(float startX, float startY, float velocityX, + float velocityY); + + void onScale(float scaleFactor, float focusX, float focusY); + +} \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnMatrixChangedListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnMatrixChangedListener.java new file mode 100644 index 0000000..f3031d6 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnMatrixChangedListener.java @@ -0,0 +1,18 @@ +package com.github.chrisbanes.photoview; + +import android.graphics.RectF; + +/** + * Interface definition for a callback to be invoked when the internal Matrix has changed for + * this View. + */ +public interface OnMatrixChangedListener { + + /** + * Callback for when the Matrix displaying the Drawable has changed. This could be because + * the View's bounds have changed, or the user has zoomed. + * + * @param rect - Rectangle displaying the Drawable's new bounds. + */ + void onMatrixChanged(RectF rect); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnOutsidePhotoTapListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnOutsidePhotoTapListener.java new file mode 100644 index 0000000..99fc7b4 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnOutsidePhotoTapListener.java @@ -0,0 +1,14 @@ +package com.github.chrisbanes.photoview; + +import android.widget.ImageView; + +/** + * Callback when the user tapped outside of the photo + */ +public interface OnOutsidePhotoTapListener { + + /** + * The outside of the photo has been tapped + */ + void onOutsidePhotoTap(ImageView imageView); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnPhotoTapListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnPhotoTapListener.java new file mode 100644 index 0000000..5f6f070 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnPhotoTapListener.java @@ -0,0 +1,22 @@ +package com.github.chrisbanes.photoview; + +import android.widget.ImageView; + +/** + * A callback to be invoked when the Photo is tapped with a single + * tap. + */ +public interface OnPhotoTapListener { + + /** + * A callback to receive where the user taps on a photo. You will only receive a callback if + * the user taps on the actual photo, tapping on 'whitespace' will be ignored. + * + * @param view ImageView the user tapped. + * @param x where the user tapped from the of the Drawable, as percentage of the + * Drawable width. + * @param y where the user tapped from the top of the Drawable, as percentage of the + * Drawable height. + */ + void onPhotoTap(ImageView view, float x, float y); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnScaleChangedListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnScaleChangedListener.java new file mode 100644 index 0000000..c6bb7a6 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnScaleChangedListener.java @@ -0,0 +1,17 @@ +package com.github.chrisbanes.photoview; + + +/** + * Interface definition for callback to be invoked when attached ImageView scale changes + */ +public interface OnScaleChangedListener { + + /** + * Callback for when the scale changes + * + * @param scaleFactor the scale factor (less than 1 for zoom out, greater than 1 for zoom in) + * @param focusX focal point X position + * @param focusY focal point Y position + */ + void onScaleChange(float scaleFactor, float focusX, float focusY); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnSingleFlingListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnSingleFlingListener.java new file mode 100644 index 0000000..f5dab92 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnSingleFlingListener.java @@ -0,0 +1,21 @@ +package com.github.chrisbanes.photoview; + +import android.view.MotionEvent; + +/** + * A callback to be invoked when the ImageView is flung with a single + * touch + */ +public interface OnSingleFlingListener { + + /** + * A callback to receive where the user flings on a ImageView. You will receive a callback if + * the user flings anywhere on the view. + * + * @param e1 MotionEvent the user first touch. + * @param e2 MotionEvent the user last touch. + * @param velocityX distance of user's horizontal fling. + * @param velocityY distance of user's vertical fling. + */ + boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewDragListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewDragListener.java new file mode 100644 index 0000000..66999a5 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewDragListener.java @@ -0,0 +1,16 @@ +package com.github.chrisbanes.photoview; + +/** + * Interface definition for a callback to be invoked when the photo is experiencing a drag event + */ +public interface OnViewDragListener { + + /** + * Callback for when the photo is experiencing a drag event. This cannot be invoked when the + * user is scaling. + * + * @param dx The change of the coordinates in the x-direction + * @param dy The change of the coordinates in the y-direction + */ + void onDrag(float dx, float dy); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewTapListener.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewTapListener.java new file mode 100644 index 0000000..6856255 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/OnViewTapListener.java @@ -0,0 +1,16 @@ +package com.github.chrisbanes.photoview; + +import android.view.View; + +public interface OnViewTapListener { + + /** + * A callback to receive where the user taps on a ImageView. You will receive a callback if + * the user taps anywhere on the view, tapping on 'whitespace' will not be ignored. + * + * @param view - View the user tapped. + * @param x - where the user tapped from the left of the View. + * @param y - where the user tapped from the top of the View. + */ + void onViewTap(View view, float x, float y); +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoView.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoView.java new file mode 100644 index 0000000..8a8ba0a --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoView.java @@ -0,0 +1,256 @@ +/* + Copyright 2011, 2012 Chris Banes. +

+ 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.github.chrisbanes.photoview; + +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.util.AttributeSet; +import android.view.GestureDetector; + +import androidx.appcompat.widget.AppCompatImageView; + +/** + * A zoomable ImageView. See {@link PhotoViewAttacher} for most of the details on how the zooming + * is accomplished + */ +@SuppressWarnings("unused") +public class PhotoView extends AppCompatImageView { + + private PhotoViewAttacher attacher; + private ScaleType pendingScaleType; + + public PhotoView(Context context) { + this(context, null); + } + + public PhotoView(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public PhotoView(Context context, AttributeSet attr, int defStyle) { + super(context, attr, defStyle); + init(); + } + + private void init() { + attacher = new PhotoViewAttacher(this); + //We always pose as a Matrix scale type, though we can change to another scale type + //via the attacher + super.setScaleType(ScaleType.MATRIX); + //apply the previously applied scale type + if (pendingScaleType != null) { + setScaleType(pendingScaleType); + pendingScaleType = null; + } + } + + /** + * Get the current {@link PhotoViewAttacher} for this view. Be wary of holding on to references + * to this attacher, as it has a reference to this view, which, if a reference is held in the + * wrong place, can cause memory leaks. + * + * @return the attacher. + */ + public PhotoViewAttacher getAttacher() { + return attacher; + } + + @Override + public ScaleType getScaleType() { + return attacher.getScaleType(); + } + + @Override + public Matrix getImageMatrix() { + return attacher.getImageMatrix(); + } + + @Override + public void setOnLongClickListener(OnLongClickListener l) { + attacher.setOnLongClickListener(l); + } + + @Override + public void setOnClickListener(OnClickListener l) { + attacher.setOnClickListener(l); + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (attacher == null) { + pendingScaleType = scaleType; + } else { + attacher.setScaleType(scaleType); + } + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + // setImageBitmap calls through to this method + if (attacher != null) { + attacher.update(); + } + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + if (attacher != null) { + attacher.update(); + } + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + if (attacher != null) { + attacher.update(); + } + } + + @Override + protected boolean setFrame(int l, int t, int r, int b) { + boolean changed = super.setFrame(l, t, r, b); + if (changed) { + attacher.update(); + } + return changed; + } + + public void setRotationTo(float rotationDegree) { + attacher.setRotationTo(rotationDegree); + } + + public void setRotationBy(float rotationDegree) { + attacher.setRotationBy(rotationDegree); + } + + public boolean isZoomable() { + return attacher.isZoomable(); + } + + public void setZoomable(boolean zoomable) { + attacher.setZoomable(zoomable); + } + + public RectF getDisplayRect() { + return attacher.getDisplayRect(); + } + + public void getDisplayMatrix(Matrix matrix) { + attacher.getDisplayMatrix(matrix); + } + + @SuppressWarnings("UnusedReturnValue") public boolean setDisplayMatrix(Matrix finalRectangle) { + return attacher.setDisplayMatrix(finalRectangle); + } + + public void getSuppMatrix(Matrix matrix) { + attacher.getSuppMatrix(matrix); + } + + public boolean setSuppMatrix(Matrix matrix) { + return attacher.setDisplayMatrix(matrix); + } + + public float getMinimumScale() { + return attacher.getMinimumScale(); + } + + public float getMediumScale() { + return attacher.getMediumScale(); + } + + public float getMaximumScale() { + return attacher.getMaximumScale(); + } + + public float getScale() { + return attacher.getScale(); + } + + public void setAllowParentInterceptOnEdge(boolean allow) { + attacher.setAllowParentInterceptOnEdge(allow); + } + + public void setMinimumScale(float minimumScale) { + attacher.setMinimumScale(minimumScale); + } + + public void setMediumScale(float mediumScale) { + attacher.setMediumScale(mediumScale); + } + + public void setMaximumScale(float maximumScale) { + attacher.setMaximumScale(maximumScale); + } + + public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) { + attacher.setScaleLevels(minimumScale, mediumScale, maximumScale); + } + + public void setOnMatrixChangeListener(OnMatrixChangedListener listener) { + attacher.setOnMatrixChangeListener(listener); + } + + public void setOnPhotoTapListener(OnPhotoTapListener listener) { + attacher.setOnPhotoTapListener(listener); + } + + public void setOnOutsidePhotoTapListener(OnOutsidePhotoTapListener listener) { + attacher.setOnOutsidePhotoTapListener(listener); + } + + public void setOnViewTapListener(OnViewTapListener listener) { + attacher.setOnViewTapListener(listener); + } + + public void setOnViewDragListener(OnViewDragListener listener) { + attacher.setOnViewDragListener(listener); + } + + public void setScale(float scale) { + attacher.setScale(scale); + } + + public void setScale(float scale, boolean animate) { + attacher.setScale(scale, animate); + } + + public void setScale(float scale, float focalX, float focalY, boolean animate) { + attacher.setScale(scale, focalX, focalY, animate); + } + + public void setZoomTransitionDuration(int milliseconds) { + attacher.setZoomTransitionDuration(milliseconds); + } + + public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) { + attacher.setOnDoubleTapListener(onDoubleTapListener); + } + + public void setOnScaleChangeListener(OnScaleChangedListener onScaleChangedListener) { + attacher.setOnScaleChangeListener(onScaleChangedListener); + } + + public void setOnSingleFlingListener(OnSingleFlingListener onSingleFlingListener) { + attacher.setOnSingleFlingListener(onSingleFlingListener); + } +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoViewAttacher.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoViewAttacher.java new file mode 100755 index 0000000..faf3491 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/PhotoViewAttacher.java @@ -0,0 +1,822 @@ +/* + Copyright 2011, 2012 Chris Banes. +

+ 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.github.chrisbanes.photoview; + +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.Matrix.ScaleToFit; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnLongClickListener; +import android.view.ViewParent; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.OverScroller; + +/** + * The component of {@link PhotoView} which does the work allowing for zooming, scaling, panning, etc. + * It is made public in case you need to subclass something other than AppCompatImageView and still + * gain the functionality that {@link PhotoView} offers + */ +public class PhotoViewAttacher implements View.OnTouchListener, + View.OnLayoutChangeListener { + + private static float DEFAULT_MAX_SCALE = 3.0f; + private static float DEFAULT_MID_SCALE = 1.75f; + private static float DEFAULT_MIN_SCALE = 1.0f; + private static int DEFAULT_ZOOM_DURATION = 200; + + private static final int HORIZONTAL_EDGE_NONE = -1; + private static final int HORIZONTAL_EDGE_LEFT = 0; + private static final int HORIZONTAL_EDGE_RIGHT = 1; + private static final int HORIZONTAL_EDGE_BOTH = 2; + private static final int VERTICAL_EDGE_NONE = -1; + private static final int VERTICAL_EDGE_TOP = 0; + private static final int VERTICAL_EDGE_BOTTOM = 1; + private static final int VERTICAL_EDGE_BOTH = 2; + private static int SINGLE_TOUCH = 1; + + private Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); + private int mZoomDuration = DEFAULT_ZOOM_DURATION; + private float mMinScale = DEFAULT_MIN_SCALE; + private float mMidScale = DEFAULT_MID_SCALE; + private float mMaxScale = DEFAULT_MAX_SCALE; + + private boolean mAllowParentInterceptOnEdge = true; + private boolean mBlockParentIntercept = false; + + private ImageView mImageView; + + // Gesture Detectors + private GestureDetector mGestureDetector; + private CustomGestureDetector mScaleDragDetector; + + // These are set so we don't keep allocating them on the heap + private final Matrix mBaseMatrix = new Matrix(); + private final Matrix mDrawMatrix = new Matrix(); + private final Matrix mSuppMatrix = new Matrix(); + private final RectF mDisplayRect = new RectF(); + private final float[] mMatrixValues = new float[9]; + + // Listeners + private OnMatrixChangedListener mMatrixChangeListener; + private OnPhotoTapListener mPhotoTapListener; + private OnOutsidePhotoTapListener mOutsidePhotoTapListener; + private OnViewTapListener mViewTapListener; + private View.OnClickListener mOnClickListener; + private OnLongClickListener mLongClickListener; + private OnScaleChangedListener mScaleChangeListener; + private OnSingleFlingListener mSingleFlingListener; + private OnViewDragListener mOnViewDragListener; + + private FlingRunnable mCurrentFlingRunnable; + private int mHorizontalScrollEdge = HORIZONTAL_EDGE_BOTH; + private int mVerticalScrollEdge = VERTICAL_EDGE_BOTH; + private float mBaseRotation; + + private boolean mZoomEnabled = true; + private ScaleType mScaleType = ScaleType.FIT_CENTER; + + private OnGestureListener onGestureListener = new OnGestureListener() { + @Override + public void onDrag(float dx, float dy) { + if (mScaleDragDetector.isScaling()) { + return; // Do not drag if we are already scaling + } + if (mOnViewDragListener != null) { + mOnViewDragListener.onDrag(dx, dy); + } + mSuppMatrix.postTranslate(dx, dy); + checkAndDisplayMatrix(); + + /* + * Here we decide whether to let the ImageView's parent to start taking + * over the touch event. + * + * First we check whether this function is enabled. We never want the + * parent to take over if we're scaling. We then check the edge we're + * on, and the direction of the scroll (i.e. if we're pulling against + * the edge, aka 'overscrolling', let the parent take over). + */ + ViewParent parent = mImageView.getParent(); + if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) { + if (mHorizontalScrollEdge == HORIZONTAL_EDGE_BOTH + || (mHorizontalScrollEdge == HORIZONTAL_EDGE_LEFT && dx >= 1f) + || (mHorizontalScrollEdge == HORIZONTAL_EDGE_RIGHT && dx <= -1f) + || (mVerticalScrollEdge == VERTICAL_EDGE_TOP && dy >= 1f) + || (mVerticalScrollEdge == VERTICAL_EDGE_BOTTOM && dy <= -1f)) { + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(false); + } + } + } else { + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + } + + @Override + public void onFling(float startX, float startY, float velocityX, float velocityY) { + mCurrentFlingRunnable = new FlingRunnable(mImageView.getContext()); + mCurrentFlingRunnable.fling(getImageViewWidth(mImageView), + getImageViewHeight(mImageView), (int) velocityX, (int) velocityY); + mImageView.post(mCurrentFlingRunnable); + } + + @Override + public void onScale(float scaleFactor, float focusX, float focusY) { + if (getScale() < mMaxScale || scaleFactor < 1f) { + if (mScaleChangeListener != null) { + mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY); + } + mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY); + checkAndDisplayMatrix(); + } + } + }; + + public PhotoViewAttacher(ImageView imageView) { + mImageView = imageView; + imageView.setOnTouchListener(this); + imageView.addOnLayoutChangeListener(this); + if (imageView.isInEditMode()) { + return; + } + mBaseRotation = 0.0f; + // Create Gesture Detectors... + mScaleDragDetector = new CustomGestureDetector(imageView.getContext(), onGestureListener); + mGestureDetector = new GestureDetector(imageView.getContext(), new GestureDetector.SimpleOnGestureListener() { + + // forward long click listener + @Override + public void onLongPress(MotionEvent e) { + if (mLongClickListener != null) { + mLongClickListener.onLongClick(mImageView); + } + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, + float velocityX, float velocityY) { + if (mSingleFlingListener != null) { + if (getScale() > DEFAULT_MIN_SCALE) { + return false; + } + if (e1.getPointerCount() > SINGLE_TOUCH + || e2.getPointerCount() > SINGLE_TOUCH) { + return false; + } + return mSingleFlingListener.onFling(e1, e2, velocityX, velocityY); + } + return false; + } + }); + mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (mOnClickListener != null) { + mOnClickListener.onClick(mImageView); + } + final RectF displayRect = getDisplayRect(); + final float x = e.getX(), y = e.getY(); + if (mViewTapListener != null) { + mViewTapListener.onViewTap(mImageView, x, y); + } + if (displayRect != null) { + // Check to see if the user tapped on the photo + if (displayRect.contains(x, y)) { + float xResult = (x - displayRect.left) + / displayRect.width(); + float yResult = (y - displayRect.top) + / displayRect.height(); + if (mPhotoTapListener != null) { + mPhotoTapListener.onPhotoTap(mImageView, xResult, yResult); + } + return true; + } else { + if (mOutsidePhotoTapListener != null) { + mOutsidePhotoTapListener.onOutsidePhotoTap(mImageView); + } + } + } + return false; + } + + @Override + public boolean onDoubleTap(MotionEvent ev) { + try { + float scale = getScale(); + float x = ev.getX(); + float y = ev.getY(); + if (scale < getMediumScale()) { + setScale(getMediumScale(), x, y, true); + } else if (scale >= getMediumScale() && scale < getMaximumScale()) { + setScale(getMaximumScale(), x, y, true); + } else { + setScale(getMinimumScale(), x, y, true); + } + } catch (ArrayIndexOutOfBoundsException e) { + // Can sometimes happen when getX() and getY() is called + } + return true; + } + + @Override + public boolean onDoubleTapEvent(MotionEvent e) { + // Wait for the confirmed onDoubleTap() instead + return false; + } + }); + } + + public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) { + this.mGestureDetector.setOnDoubleTapListener(newOnDoubleTapListener); + } + + public void setOnScaleChangeListener(OnScaleChangedListener onScaleChangeListener) { + this.mScaleChangeListener = onScaleChangeListener; + } + + public void setOnSingleFlingListener(OnSingleFlingListener onSingleFlingListener) { + this.mSingleFlingListener = onSingleFlingListener; + } + + @Deprecated + public boolean isZoomEnabled() { + return mZoomEnabled; + } + + public RectF getDisplayRect() { + checkMatrixBounds(); + return getDisplayRect(getDrawMatrix()); + } + + public boolean setDisplayMatrix(Matrix finalMatrix) { + if (finalMatrix == null) { + throw new IllegalArgumentException("Matrix cannot be null"); + } + if (mImageView.getDrawable() == null) { + return false; + } + mSuppMatrix.set(finalMatrix); + checkAndDisplayMatrix(); + return true; + } + + public void setBaseRotation(final float degrees) { + mBaseRotation = degrees % 360; + update(); + setRotationBy(mBaseRotation); + checkAndDisplayMatrix(); + } + + public void setRotationTo(float degrees) { + mSuppMatrix.setRotate(degrees % 360); + checkAndDisplayMatrix(); + } + + public void setRotationBy(float degrees) { + mSuppMatrix.postRotate(degrees % 360); + checkAndDisplayMatrix(); + } + + public float getMinimumScale() { + return mMinScale; + } + + public float getMediumScale() { + return mMidScale; + } + + public float getMaximumScale() { + return mMaxScale; + } + + public float getScale() { + return (float) Math.sqrt((float) Math.pow(getValue(mSuppMatrix, Matrix.MSCALE_X), 2) + (float) Math.pow + (getValue(mSuppMatrix, Matrix.MSKEW_Y), 2)); + } + + public ScaleType getScaleType() { + return mScaleType; + } + + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int + oldRight, int oldBottom) { + // Update our base matrix, as the bounds have changed + if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) { + updateBaseMatrix(mImageView.getDrawable()); + } + } + + @Override + public boolean onTouch(View v, MotionEvent ev) { + boolean handled = false; + if (mZoomEnabled && Util.hasDrawable((ImageView) v)) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + ViewParent parent = v.getParent(); + // First, disable the Parent from intercepting the touch + // event + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + // If we're flinging, and the user presses down, cancel + // fling + cancelFling(); + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + // If the user has zoomed less than min scale, zoom back + // to min scale + if (getScale() < mMinScale) { + RectF rect = getDisplayRect(); + if (rect != null) { + v.post(new AnimatedZoomRunnable(getScale(), mMinScale, + rect.centerX(), rect.centerY())); + handled = true; + } + } else if (getScale() > mMaxScale) { + RectF rect = getDisplayRect(); + if (rect != null) { + v.post(new AnimatedZoomRunnable(getScale(), mMaxScale, + rect.centerX(), rect.centerY())); + handled = true; + } + } + break; + } + // Try the Scale/Drag detector + if (mScaleDragDetector != null) { + boolean wasScaling = mScaleDragDetector.isScaling(); + boolean wasDragging = mScaleDragDetector.isDragging(); + handled = mScaleDragDetector.onTouchEvent(ev); + boolean didntScale = !wasScaling && !mScaleDragDetector.isScaling(); + boolean didntDrag = !wasDragging && !mScaleDragDetector.isDragging(); + mBlockParentIntercept = didntScale && didntDrag; + } + // Check to see if the user double tapped + if (mGestureDetector != null && mGestureDetector.onTouchEvent(ev)) { + handled = true; + } + + } + return handled; + } + + public void setAllowParentInterceptOnEdge(boolean allow) { + mAllowParentInterceptOnEdge = allow; + } + + public void setMinimumScale(float minimumScale) { + Util.checkZoomLevels(minimumScale, mMidScale, mMaxScale); + mMinScale = minimumScale; + } + + public void setMediumScale(float mediumScale) { + Util.checkZoomLevels(mMinScale, mediumScale, mMaxScale); + mMidScale = mediumScale; + } + + public void setMaximumScale(float maximumScale) { + Util.checkZoomLevels(mMinScale, mMidScale, maximumScale); + mMaxScale = maximumScale; + } + + public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) { + Util.checkZoomLevels(minimumScale, mediumScale, maximumScale); + mMinScale = minimumScale; + mMidScale = mediumScale; + mMaxScale = maximumScale; + } + + public void setOnLongClickListener(OnLongClickListener listener) { + mLongClickListener = listener; + } + + public void setOnClickListener(View.OnClickListener listener) { + mOnClickListener = listener; + } + + public void setOnMatrixChangeListener(OnMatrixChangedListener listener) { + mMatrixChangeListener = listener; + } + + public void setOnPhotoTapListener(OnPhotoTapListener listener) { + mPhotoTapListener = listener; + } + + public void setOnOutsidePhotoTapListener(OnOutsidePhotoTapListener mOutsidePhotoTapListener) { + this.mOutsidePhotoTapListener = mOutsidePhotoTapListener; + } + + public void setOnViewTapListener(OnViewTapListener listener) { + mViewTapListener = listener; + } + + public void setOnViewDragListener(OnViewDragListener listener) { + mOnViewDragListener = listener; + } + + public void setScale(float scale) { + setScale(scale, false); + } + + public void setScale(float scale, boolean animate) { + setScale(scale, + (mImageView.getRight()) / 2, + (mImageView.getBottom()) / 2, + animate); + } + + public void setScale(float scale, float focalX, float focalY, + boolean animate) { + // Check to see if the scale is within bounds + if (scale < mMinScale || scale > mMaxScale) { + throw new IllegalArgumentException("Scale must be within the range of minScale and maxScale"); + } + if (animate) { + mImageView.post(new AnimatedZoomRunnable(getScale(), scale, + focalX, focalY)); + } else { + mSuppMatrix.setScale(scale, scale, focalX, focalY); + checkAndDisplayMatrix(); + } + } + + /** + * Set the zoom interpolator + * + * @param interpolator the zoom interpolator + */ + public void setZoomInterpolator(Interpolator interpolator) { + mInterpolator = interpolator; + } + + public void setScaleType(ScaleType scaleType) { + if (Util.isSupportedScaleType(scaleType) && scaleType != mScaleType) { + mScaleType = scaleType; + update(); + } + } + + public boolean isZoomable() { + return mZoomEnabled; + } + + public void setZoomable(boolean zoomable) { + mZoomEnabled = zoomable; + update(); + } + + public void update() { + if (mZoomEnabled) { + // Update the base matrix using the current drawable + updateBaseMatrix(mImageView.getDrawable()); + } else { + // Reset the Matrix... + resetMatrix(); + } + } + + /** + * Get the display matrix + * + * @param matrix target matrix to copy to + */ + public void getDisplayMatrix(Matrix matrix) { + matrix.set(getDrawMatrix()); + } + + /** + * Get the current support matrix + */ + public void getSuppMatrix(Matrix matrix) { + matrix.set(mSuppMatrix); + } + + private Matrix getDrawMatrix() { + mDrawMatrix.set(mBaseMatrix); + mDrawMatrix.postConcat(mSuppMatrix); + return mDrawMatrix; + } + + public Matrix getImageMatrix() { + return mDrawMatrix; + } + + public void setZoomTransitionDuration(int milliseconds) { + this.mZoomDuration = milliseconds; + } + + /** + * Helper method that 'unpacks' a Matrix and returns the required value + * + * @param matrix Matrix to unpack + * @param whichValue Which value from Matrix.M* to return + * @return returned value + */ + private float getValue(Matrix matrix, int whichValue) { + matrix.getValues(mMatrixValues); + return mMatrixValues[whichValue]; + } + + /** + * Resets the Matrix back to FIT_CENTER, and then displays its contents + */ + private void resetMatrix() { + mSuppMatrix.reset(); + setRotationBy(mBaseRotation); + setImageViewMatrix(getDrawMatrix()); + checkMatrixBounds(); + } + + private void setImageViewMatrix(Matrix matrix) { + mImageView.setImageMatrix(matrix); + // Call MatrixChangedListener if needed + if (mMatrixChangeListener != null) { + RectF displayRect = getDisplayRect(matrix); + if (displayRect != null) { + mMatrixChangeListener.onMatrixChanged(displayRect); + } + } + } + + /** + * Helper method that simply checks the Matrix, and then displays the result + */ + private void checkAndDisplayMatrix() { + if (checkMatrixBounds()) { + setImageViewMatrix(getDrawMatrix()); + } + } + + /** + * Helper method that maps the supplied Matrix to the current Drawable + * + * @param matrix - Matrix to map Drawable against + * @return RectF - Displayed Rectangle + */ + private RectF getDisplayRect(Matrix matrix) { + Drawable d = mImageView.getDrawable(); + if (d != null) { + mDisplayRect.set(0, 0, d.getIntrinsicWidth(), + d.getIntrinsicHeight()); + matrix.mapRect(mDisplayRect); + return mDisplayRect; + } + return null; + } + + /** + * Calculate Matrix for FIT_CENTER + * + * @param drawable - Drawable being displayed + */ + private void updateBaseMatrix(Drawable drawable) { + if (drawable == null) { + return; + } + final float viewWidth = getImageViewWidth(mImageView); + final float viewHeight = getImageViewHeight(mImageView); + final int drawableWidth = drawable.getIntrinsicWidth(); + final int drawableHeight = drawable.getIntrinsicHeight(); + mBaseMatrix.reset(); + final float widthScale = viewWidth / drawableWidth; + final float heightScale = viewHeight / drawableHeight; + if (mScaleType == ScaleType.CENTER) { + mBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F, + (viewHeight - drawableHeight) / 2F); + + } else if (mScaleType == ScaleType.CENTER_CROP) { + float scale = Math.max(widthScale, heightScale); + mBaseMatrix.postScale(scale, scale); + + /*mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F, + (viewHeight - drawableHeight * scale) / 2F);*/ + + // FOX: make CENTER_CROP act like TOP_CROP + mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F, + 0); + + } else if (mScaleType == ScaleType.CENTER_INSIDE) { + float scale = Math.min(1.0f, Math.min(widthScale, heightScale)); + mBaseMatrix.postScale(scale, scale); + mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F, + (viewHeight - drawableHeight * scale) / 2F); + + } else { + RectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight); + RectF mTempDst = new RectF(0, 0, viewWidth, viewHeight); + if ((int) mBaseRotation % 180 != 0) { + mTempSrc = new RectF(0, 0, drawableHeight, drawableWidth); + } + switch (mScaleType) { + case FIT_CENTER: + mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER); + break; + case FIT_START: + mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.START); + break; + case FIT_END: + mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.END); + break; + case FIT_XY: + mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.FILL); + break; + default: + break; + } + } + resetMatrix(); + } + + private boolean checkMatrixBounds() { + final RectF rect = getDisplayRect(getDrawMatrix()); + if (rect == null) { + return false; + } + final float height = rect.height(), width = rect.width(); + float deltaX = 0, deltaY = 0; + final int viewHeight = getImageViewHeight(mImageView); + if (height <= viewHeight) { + switch (mScaleType) { + case FIT_START: + deltaY = -rect.top; + break; + case FIT_END: + deltaY = viewHeight - height - rect.top; + break; + default: + deltaY = (viewHeight - height) / 2 - rect.top; + break; + } + mVerticalScrollEdge = VERTICAL_EDGE_BOTH; + } else if (rect.top > 0) { + mVerticalScrollEdge = VERTICAL_EDGE_TOP; + deltaY = -rect.top; + } else if (rect.bottom < viewHeight) { + mVerticalScrollEdge = VERTICAL_EDGE_BOTTOM; + deltaY = viewHeight - rect.bottom; + } else { + mVerticalScrollEdge = VERTICAL_EDGE_NONE; + } + final int viewWidth = getImageViewWidth(mImageView); + if (width <= viewWidth) { + switch (mScaleType) { + case FIT_START: + deltaX = -rect.left; + break; + case FIT_END: + deltaX = viewWidth - width - rect.left; + break; + default: + deltaX = (viewWidth - width) / 2 - rect.left; + break; + } + mHorizontalScrollEdge = HORIZONTAL_EDGE_BOTH; + } else if (rect.left > 0) { + mHorizontalScrollEdge = HORIZONTAL_EDGE_LEFT; + deltaX = -rect.left; + } else if (rect.right < viewWidth) { + deltaX = viewWidth - rect.right; + mHorizontalScrollEdge = HORIZONTAL_EDGE_RIGHT; + } else { + mHorizontalScrollEdge = HORIZONTAL_EDGE_NONE; + } + // Finally actually translate the matrix + mSuppMatrix.postTranslate(deltaX, deltaY); + return true; + } + + private int getImageViewWidth(ImageView imageView) { + return imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight(); + } + + private int getImageViewHeight(ImageView imageView) { + return imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom(); + } + + private void cancelFling() { + if (mCurrentFlingRunnable != null) { + mCurrentFlingRunnable.cancelFling(); + mCurrentFlingRunnable = null; + } + } + + private class AnimatedZoomRunnable implements Runnable { + + private final float mFocalX, mFocalY; + private final long mStartTime; + private final float mZoomStart, mZoomEnd; + + public AnimatedZoomRunnable(final float currentZoom, final float targetZoom, + final float focalX, final float focalY) { + mFocalX = focalX; + mFocalY = focalY; + mStartTime = System.currentTimeMillis(); + mZoomStart = currentZoom; + mZoomEnd = targetZoom; + } + + @Override + public void run() { + float t = interpolate(); + float scale = mZoomStart + t * (mZoomEnd - mZoomStart); + float deltaScale = scale / getScale(); + onGestureListener.onScale(deltaScale, mFocalX, mFocalY); + // We haven't hit our target scale yet, so post ourselves again + if (t < 1f) { + Compat.postOnAnimation(mImageView, this); + } + } + + private float interpolate() { + float t = 1f * (System.currentTimeMillis() - mStartTime) / mZoomDuration; + t = Math.min(1f, t); + t = mInterpolator.getInterpolation(t); + return t; + } + } + + private class FlingRunnable implements Runnable { + + private final OverScroller mScroller; + private int mCurrentX, mCurrentY; + + public FlingRunnable(Context context) { + mScroller = new OverScroller(context); + } + + public void cancelFling() { + mScroller.forceFinished(true); + } + + public void fling(int viewWidth, int viewHeight, int velocityX, + int velocityY) { + final RectF rect = getDisplayRect(); + if (rect == null) { + return; + } + final int startX = Math.round(-rect.left); + final int minX, maxX, minY, maxY; + if (viewWidth < rect.width()) { + minX = 0; + maxX = Math.round(rect.width() - viewWidth); + } else { + minX = maxX = startX; + } + final int startY = Math.round(-rect.top); + if (viewHeight < rect.height()) { + minY = 0; + maxY = Math.round(rect.height() - viewHeight); + } else { + minY = maxY = startY; + } + mCurrentX = startX; + mCurrentY = startY; + // If we actually can move, fling the scroller + if (startX != maxX || startY != maxY) { + mScroller.fling(startX, startY, velocityX, velocityY, minX, + maxX, minY, maxY, 0, 0); + } + } + + @Override + public void run() { + if (mScroller.isFinished()) { + return; // remaining post that should not be handled + } + if (mScroller.computeScrollOffset()) { + final int newX = mScroller.getCurrX(); + final int newY = mScroller.getCurrY(); + mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY); + checkAndDisplayMatrix(); + mCurrentX = newX; + mCurrentY = newY; + // Post On animation + Compat.postOnAnimation(mImageView, this); + } + } + } +} diff --git a/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Util.java b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Util.java new file mode 100644 index 0000000..2e3e5ad --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/chrisbanes/photoview/Util.java @@ -0,0 +1,37 @@ +package com.github.chrisbanes.photoview; + +import android.view.MotionEvent; +import android.widget.ImageView; + +class Util { + + static void checkZoomLevels(float minZoom, float midZoom, + float maxZoom) { + if (minZoom >= midZoom) { + throw new IllegalArgumentException( + "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value"); + } else if (midZoom >= maxZoom) { + throw new IllegalArgumentException( + "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value"); + } + } + + static boolean hasDrawable(ImageView imageView) { + return imageView.getDrawable() != null; + } + + static boolean isSupportedScaleType(final ImageView.ScaleType scaleType) { + if (scaleType == null) { + return false; + } + switch (scaleType) { + case MATRIX: + throw new IllegalStateException("Matrix scale type is not supported"); + } + return true; + } + + static int getPointerIndex(int action) { + return (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + } +} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java deleted file mode 100644 index 73392b1..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java +++ /dev/null @@ -1,268 +0,0 @@ -package it.sephiroth.android.library.imagezoom; - -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.Log; -import android.view.GestureDetector; -import android.view.GestureDetector.OnGestureListener; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.ScaleGestureDetector.OnScaleGestureListener; -import android.view.ViewConfiguration; - -public class ImageViewTouch extends ImageViewTouchBase { - - private static final float SCROLL_DELTA_THRESHOLD = 1.0f; - static final float MIN_ZOOM = 0.9f; - protected ScaleGestureDetector mScaleDetector; - protected GestureDetector mGestureDetector; - protected int mTouchSlop; - protected float mCurrentScaleFactor; - protected float mScaleFactor; - protected int mDoubleTapDirection; - protected OnGestureListener mGestureListener; - protected OnScaleGestureListener mScaleListener; - protected boolean mDoubleTapToZoomEnabled = true; - protected boolean mScaleEnabled = true; - protected boolean mScrollEnabled = true; - - private OnImageViewTouchDoubleTapListener doubleTapListener; - - public interface OnScaleChangedListener { - public void onScaleChanged(float scale); - } - - protected OnScaleChangedListener mScaleChangedListener; - - public ImageViewTouch( Context context, AttributeSet attrs ) { - super( context, attrs ); - } - - @Override - protected void init() { - super.init(); - mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); - mGestureListener = getGestureListener(); - mScaleListener = getScaleListener(); - - mScaleDetector = new ScaleGestureDetector( getContext(), mScaleListener ); - mGestureDetector = new GestureDetector( getContext(), mGestureListener, null, true ); - - mCurrentScaleFactor = 1f; - mDoubleTapDirection = 1; - } - - public void setDoubleTapListener( OnImageViewTouchDoubleTapListener doubleTapListener ){ - this.doubleTapListener = doubleTapListener; - } - - public void setDoubleTapToZoomEnabled( boolean value ) { - mDoubleTapToZoomEnabled = value; - } - - public void setScaleEnabled( boolean value ) { - mScaleEnabled = value; - } - - public void setScrollEnabled( boolean value ) { - mScrollEnabled = value; - } - - public boolean getDoubleTapEnabled() { - return mDoubleTapToZoomEnabled; - } - - protected OnGestureListener getGestureListener() { - return new GestureListener(); - } - - protected OnScaleGestureListener getScaleListener() { - return new ScaleListener(); - } - - @Override - protected void onBitmapChanged( Drawable drawable ) { - super.onBitmapChanged( drawable ); - - float v[] = new float[9]; - mSuppMatrix.getValues( v ); - mCurrentScaleFactor = v[Matrix.MSCALE_X]; - } - - @Override - protected void _setImageDrawable( final Drawable drawable, final boolean reset, final Matrix initial_matrix, final float maxZoom ) { - super._setImageDrawable( drawable, reset, initial_matrix, maxZoom ); - mScaleFactor = getMaxZoom() / 3; - } - - @Override - public boolean onTouchEvent( MotionEvent event ) { - mScaleDetector.onTouchEvent( event ); - if ( !mScaleDetector.isInProgress() ) mGestureDetector.onTouchEvent( event ); - int action = event.getAction(); - switch ( action & MotionEvent.ACTION_MASK ) { - case MotionEvent.ACTION_UP: - if ( getScale() < 1f ) { - zoomTo( 1f, 50 ); - } - break; - } - return true; - } - - @Override - protected void onZoom( float scale ) { - super.onZoom( scale ); - if ( !mScaleDetector.isInProgress() ) mCurrentScaleFactor = scale; - - if (mScaleChangedListener != null) { - mScaleChangedListener.onScaleChanged(mCurrentScaleFactor); - } - } - - protected float onDoubleTapPost( float scale, float maxZoom ) { - if ( mDoubleTapDirection == 1 ) { - if (mCurrentScaleFactor - 1.0f < 0.01) { //( scale + ( mScaleFactor * 2 ) ) <= maxZoom - - float scaleFactor = mScaleFactor; - - RectF bitmapRect = getBitmapRect(); - - float w = bitmapRect.right - bitmapRect.left; - float h = bitmapRect.bottom - bitmapRect.top; - - if (w < getWidth()) { - scaleFactor = (float)getWidth() / w - scale; - } else if (h < getHeight()) { - scaleFactor = (float)getHeight() / h - scale; - } - - return scale + scaleFactor; - } else { - mDoubleTapDirection = -1; - return maxZoom; - } - } else { - mDoubleTapDirection = 1; - return 1f; - } - } - - /** - * Determines whether this ImageViewTouch can be scrolled. - * @param direction - * - positive direction value means scroll from right to left, - * negative value means scroll from left to right - * - * @return true if there is some more place to scroll, false - otherwise. - */ - public boolean canScroll(int direction) { - RectF bitmapRect = getBitmapRect(); - updateRect(bitmapRect, mScrollRect); - Rect imageViewRect = new Rect(); - getGlobalVisibleRect(imageViewRect); - - if (bitmapRect.right >= imageViewRect.right) { - if (direction < 0) { - return Math.abs(bitmapRect.right - imageViewRect.right) > SCROLL_DELTA_THRESHOLD; - } - } - - double bitmapScrollRectDelta = Math.abs(bitmapRect.left - mScrollRect.left); - return bitmapScrollRectDelta > SCROLL_DELTA_THRESHOLD; - } - - public class GestureListener extends GestureDetector.SimpleOnGestureListener { - - @Override - public boolean onDoubleTap( MotionEvent e ) { - Log.i( LOG_TAG, "onDoubleTap. double tap enabled? " + mDoubleTapToZoomEnabled); - if (mDoubleTapToZoomEnabled) { - float scale = getScale(); - float targetScale = scale; - targetScale = onDoubleTapPost( scale, getMaxZoom() ); - targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); - mCurrentScaleFactor = targetScale; - zoomTo( targetScale, e.getX(), e.getY(), 200 ); - invalidate(); - } - - if( null != doubleTapListener ){ - doubleTapListener.onDoubleTap(); - } - - return super.onDoubleTap( e ); - } - - @Override - public void onLongPress( MotionEvent e ) { - if ( isLongClickable() ) { - if ( !mScaleDetector.isInProgress() ) { - setPressed( true ); - performLongClick(); - } - } - } - - @Override - public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX, float distanceY ) { - if ( !mScrollEnabled ) return false; - - if ( e1 == null || e2 == null ) return false; - if ( e1.getPointerCount() > 1 || e2.getPointerCount() > 1 ) return false; - if ( mScaleDetector.isInProgress() ) return false; - if ( getScale() == 1f ) return false; - scrollBy( -distanceX, -distanceY ); - invalidate(); - return super.onScroll( e1, e2, distanceX, distanceY ); - } - - @Override - public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY ) { - if ( !mScrollEnabled ) return false; - - if ( e1.getPointerCount() > 1 || e2.getPointerCount() > 1 ) return false; - if ( mScaleDetector.isInProgress() ) return false; - - float diffX = e2.getX() - e1.getX(); - float diffY = e2.getY() - e1.getY(); - - if ( Math.abs( velocityX ) > 800 || Math.abs( velocityY ) > 800 ) { - scrollBy( diffX / 2, diffY / 2, 300 ); - invalidate(); - } - return super.onFling( e1, e2, velocityX, velocityY ); - } - } - - public class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - - @SuppressWarnings("unused") - @Override - public boolean onScale( ScaleGestureDetector detector ) { - float span = detector.getCurrentSpan() - detector.getPreviousSpan(); - float targetScale = mCurrentScaleFactor * detector.getScaleFactor(); - if ( mScaleEnabled ) { - targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); - zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); - mCurrentScaleFactor = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); - mDoubleTapDirection = 1; - invalidate(); - return true; - } - return false; - } - } - - public interface OnImageViewTouchDoubleTapListener { - void onDoubleTap(); - } - - public void setOnScaleChangedListener(OnScaleChangedListener listener) { - mScaleChangedListener = listener; - } -} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java deleted file mode 100755 index 8ba5b28..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java +++ /dev/null @@ -1,512 +0,0 @@ -package it.sephiroth.android.library.imagezoom; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.ImageView; - -import it.sephiroth.android.library.imagezoom.easing.Cubic; -import it.sephiroth.android.library.imagezoom.easing.Easing; -import it.sephiroth.android.library.imagezoom.graphics.FastBitmapDrawable; -import it.sephiroth.android.library.imagezoom.utils.IDisposable; - -/** - * Base View to manage image zoom/scrool/pinch operations - * - * @author alessandro - * - */ -public class ImageViewTouchBase extends ImageView implements IDisposable { - - public interface OnBitmapChangedListener { - - void onBitmapChanged( Drawable drawable ); - } - - public static final String LOG_TAG = "image"; - - protected Easing mEasing = new Cubic(); - protected Matrix mBaseMatrix = new Matrix(); - protected Matrix mSuppMatrix = new Matrix(); - protected Handler mHandler = new Handler(); - protected Runnable mOnLayoutRunnable = null; - protected float mMaxZoom; - protected final Matrix mDisplayMatrix = new Matrix(); - protected final float[] mMatrixValues = new float[9]; - protected int mThisWidth = -1, mThisHeight = -1; - protected boolean mFitToScreen = false; - protected boolean mFitToWidth = false; - final protected float MAX_ZOOM = 5.0f; - - protected RectF mBitmapRect = new RectF(); - protected RectF mCenterRect = new RectF(); - protected RectF mScrollRect = new RectF(); - - private OnBitmapChangedListener mListener; - - public ImageViewTouchBase( Context context ) { - super( context ); - init(); - } - - public ImageViewTouchBase( Context context, AttributeSet attrs ) { - super( context, attrs ); - init(); - } - - public void setOnBitmapChangedListener( OnBitmapChangedListener listener ) { - mListener = listener; - } - - protected void init() { - setScaleType( ImageView.ScaleType.MATRIX ); - } - - public void clear() { - setImageBitmap( null, true ); - } - - public void setFitToScreen( boolean value ) { - if ( value != mFitToScreen ) { - mFitToScreen = value; - requestLayout(); - } - } - - public void setFitToWidth( boolean value ) { - if ( value != mFitToWidth ) { - mFitToWidth = value; - requestLayout(); - } - } - - @Override - protected void onLayout( boolean changed, int left, int top, int right, int bottom ) { - super.onLayout( changed, left, top, right, bottom ); - mThisWidth = right - left; - mThisHeight = bottom - top; - Runnable r = mOnLayoutRunnable; - if ( r != null ) { - mOnLayoutRunnable = null; - r.run(); - } - if ( getDrawable() != null ) { - if (mFitToWidth) { - zoomToWidth(); - } else { - if (mFitToScreen) - getProperBaseMatrix2(getDrawable(), mBaseMatrix); - else - getProperBaseMatrix(getDrawable(), mBaseMatrix); - setImageMatrix(getImageViewMatrix()); - } - } - } - - @Override - public void setImageBitmap( Bitmap bm ) { - setImageBitmap( bm, true ); - } - - @Override - public void setImageResource( int resId ) { - setImageDrawable( getContext().getResources().getDrawable( resId ) ); - } - - /** - * Set the new image to display and reset the internal matrix. - * - * @param bitmap - * - the {@link Bitmap} to display - * @param reset - * - if true the image bounds will be recreated, otherwise the old {@link Matrix} is used to display the new bitmap - * @see #setImageBitmap(Bitmap) - */ - public void setImageBitmap( final Bitmap bitmap, final boolean reset ) { - setImageBitmap( bitmap, reset, null ); - } - - /** - * Similar to {@link #setImageBitmap(Bitmap, boolean)} but an optional view {@link Matrix} can be passed to determine the new - * bitmap view matrix.
- * This method is useful if you need to restore a Bitmap with the same zoom/pan values from a previous state - * - * @param bitmap - * - the {@link Bitmap} to display - * @param reset - * @param matrix - * - the {@link Matrix} to be used to display the new bitmap - * - * @see #setImageBitmap(Bitmap, boolean) - * @see #setImageBitmap(Bitmap) - * @see #getImageViewMatrix() - * @see #getDisplayMatrix() - */ - public void setImageBitmap( final Bitmap bitmap, final boolean reset, Matrix matrix ) { - setImageBitmap( bitmap, reset, matrix, -1 ); - } - - /** - * - * @param bitmap - * @param reset - * @param matrix - * @param maxZoom - * - maximum zoom allowd during zoom gestures - * - * @see #setImageBitmap(Bitmap, boolean, Matrix) - */ - public void setImageBitmap( final Bitmap bitmap, final boolean reset, Matrix matrix, float maxZoom ) { - - Log.i( LOG_TAG, "setImageBitmap: " + bitmap ); - - if ( bitmap != null ) - setImageDrawable( new FastBitmapDrawable( bitmap ), reset, matrix, maxZoom ); - else - setImageDrawable( null, reset, matrix, maxZoom ); - } - - @Override - public void setImageDrawable( Drawable drawable ) { - setImageDrawable( drawable, true, null, -1 ); - } - - public void setImageDrawable( final Drawable drawable, final boolean reset, final Matrix initial_matrix, final float maxZoom ) { - - final int viewWidth = getWidth(); - - if ( viewWidth <= 0 ) { - mOnLayoutRunnable = new Runnable() { - - @Override - public void run() { - setImageDrawable( drawable, reset, initial_matrix, maxZoom ); - } - }; - return; - } - - _setImageDrawable( drawable, reset, initial_matrix, maxZoom ); - } - - protected void _setImageDrawable( final Drawable drawable, final boolean reset, final Matrix initial_matrix, final float maxZoom ) { - - if ( drawable != null ) { - if ( mFitToScreen ) - getProperBaseMatrix2( drawable, mBaseMatrix ); - else - getProperBaseMatrix( drawable, mBaseMatrix ); - super.setImageDrawable( drawable ); - - if (mFitToWidth) zoomToWidth(); - - } else { - mBaseMatrix.reset(); - super.setImageDrawable( null ); - } - - if ( reset ) { - mSuppMatrix.reset(); - if ( initial_matrix != null ) { - mSuppMatrix = new Matrix( initial_matrix ); - } - } - - setImageMatrix( getImageViewMatrix() ); - - if ( maxZoom < 1 ) - mMaxZoom = maxZoom(); - else - mMaxZoom = maxZoom; - - onBitmapChanged( drawable ); - } - - protected void onBitmapChanged( final Drawable bitmap ) { - if ( mListener != null ) { - mListener.onBitmapChanged( bitmap ); - } - } - - protected float maxZoom() { - final Drawable drawable = getDrawable(); - - if ( drawable == null ) { - return 1F; - } - - float fw = (float) drawable.getIntrinsicWidth() / (float) mThisWidth; - float fh = (float) drawable.getIntrinsicHeight() / (float) mThisHeight; - float max = Math.max( fw, fh ) * 4; - return max; - } - - public float getMaxZoom() { - return mMaxZoom; - } - - public Matrix getImageViewMatrix() { - mDisplayMatrix.set( mBaseMatrix ); - mDisplayMatrix.postConcat( mSuppMatrix ); - return mDisplayMatrix; - } - - /** - * Returns the current image display matrix. This matrix can be used in the next call to the - * {@link #setImageBitmap(Bitmap, boolean, Matrix)} to restore the same view state of the previous {@link Bitmap} - * - * @return - */ - public Matrix getDisplayMatrix() { - return new Matrix( mSuppMatrix ); - } - - /** - * Setup the base matrix so that the image is centered and scaled properly. - * - * @param bitmap - * @param matrix - */ - protected void getProperBaseMatrix( Drawable drawable, Matrix matrix ) { - float viewWidth = getWidth(); - float viewHeight = getHeight(); - float w = drawable.getIntrinsicWidth(); - float h = drawable.getIntrinsicHeight(); - matrix.reset(); - - if ( w > viewWidth || h > viewHeight ) { - float widthScale = Math.min( viewWidth / w, 2.0f ); - float heightScale = Math.min( viewHeight / h, 2.0f ); - float scale = Math.min( widthScale, heightScale ); - matrix.postScale( scale, scale ); - float tw = ( viewWidth - w * scale ) / 2.0f; - float th = ( viewHeight - h * scale ) / 2.0f; - matrix.postTranslate( tw, th ); - } else { - float tw = ( viewWidth - w ) / 2.0f; - float th = ( viewHeight - h ) / 2.0f; - matrix.postTranslate( tw, th ); - } - } - - /** - * Setup the base matrix so that the image is centered and scaled properly. - * - * @param bitmap - * @param matrix - */ - protected void getProperBaseMatrix2( Drawable bitmap, Matrix matrix ) { - float viewWidth = getWidth(); - float viewHeight = getHeight(); - float w = bitmap.getIntrinsicWidth(); - float h = bitmap.getIntrinsicHeight(); - matrix.reset(); - float widthScale = Math.min( viewWidth / w, MAX_ZOOM ); - float heightScale = Math.min( viewHeight / h, MAX_ZOOM ); - float scale = Math.min( widthScale, heightScale ); - matrix.postScale( scale, scale ); - matrix.postTranslate( ( viewWidth - w * scale ) / 2.0f, ( viewHeight - h * scale ) / 2.0f ); - } - - protected float getValue( Matrix matrix, int whichValue ) { - matrix.getValues( mMatrixValues ); - return mMatrixValues[whichValue]; - } - - protected RectF getBitmapRect() { - final Drawable drawable = getDrawable(); - - if ( drawable == null ) return null; - Matrix m = getImageViewMatrix(); - mBitmapRect.set( 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight() ); - m.mapRect( mBitmapRect ); - return mBitmapRect; - } - - protected float getScale( Matrix matrix ) { - return getValue( matrix, Matrix.MSCALE_X ); - } - - public float getRotation() { - return 0; - } - - public float getScale() { - return getScale( mSuppMatrix ); - } - - protected void center( boolean horizontal, boolean vertical ) { - // Log.i(LOG_TAG, "center"); - final Drawable drawable = getDrawable(); - - if ( drawable == null ) return; - RectF rect = getCenter( horizontal, vertical ); - if ( rect.left != 0 || rect.top != 0 ) { - postTranslate( rect.left, rect.top ); - } - } - - protected RectF getCenter( boolean horizontal, boolean vertical ) { - final Drawable drawable = getDrawable(); - - if ( drawable == null ) return new RectF( 0, 0, 0, 0 ); - - RectF rect = getBitmapRect(); - float height = rect.height(); - float width = rect.width(); - float deltaX = 0, deltaY = 0; - if ( vertical ) { - int viewHeight = getHeight(); - if ( height < viewHeight ) { - deltaY = ( viewHeight - height ) / 2 - rect.top; - } else if ( rect.top > 0 ) { - deltaY = -rect.top; - } else if ( rect.bottom < viewHeight ) { - deltaY = getHeight() - rect.bottom; - } - } - if ( horizontal ) { - int viewWidth = getWidth(); - if ( width < viewWidth ) { - deltaX = ( viewWidth - width ) / 2 - rect.left; - } else if ( rect.left > 0 ) { - deltaX = -rect.left; - } else if ( rect.right < viewWidth ) { - deltaX = viewWidth - rect.right; - } - } - mCenterRect.set( deltaX, deltaY, 0, 0 ); - return mCenterRect; - } - - protected void postTranslate( float deltaX, float deltaY ) { - mSuppMatrix.postTranslate( deltaX, deltaY ); - setImageMatrix( getImageViewMatrix() ); - } - - protected void postScale( float scale, float centerX, float centerY ) { - mSuppMatrix.postScale( scale, scale, centerX, centerY ); - setImageMatrix( getImageViewMatrix() ); - } - - protected void zoomTo( float scale ) { - float cx = getWidth() / 2F; - float cy = getHeight() / 2F; - zoomTo( scale, cx, cy ); - } - - public void zoomTo( float scale, float durationMs ) { - float cx = getWidth() / 2F; - float cy = getHeight() / 2F; - zoomTo( scale, cx, cy, durationMs ); - } - - protected void zoomTo( float scale, float centerX, float centerY ) { - if ( scale > mMaxZoom ) scale = mMaxZoom; - float oldScale = getScale(); - float deltaScale = scale / oldScale; - postScale( deltaScale, centerX, centerY ); - onZoom( getScale() ); - center( true, true ); - } - - protected void onZoom( float scale ) {} - - public void scrollBy( float x, float y ) { - panBy( x, y ); - } - - protected void panBy( double dx, double dy ) { - RectF rect = getBitmapRect(); - mScrollRect.set( (float) dx, (float) dy, 0, 0 ); - updateRect( rect, mScrollRect ); - postTranslate( mScrollRect.left, mScrollRect.top ); - center( true, true ); - } - - protected void updateRect( RectF bitmapRect, RectF scrollRect ) { - float width = getWidth(); - float height = getHeight(); - - if ( bitmapRect.top >= 0 && bitmapRect.bottom <= height ) scrollRect.top = 0; - if ( bitmapRect.left >= 0 && bitmapRect.right <= width ) scrollRect.left = 0; - if ( bitmapRect.top + scrollRect.top >= 0 && bitmapRect.bottom > height ) scrollRect.top = (int) ( 0 - bitmapRect.top ); - if ( bitmapRect.bottom + scrollRect.top <= ( height - 0 ) && bitmapRect.top < 0 ) - scrollRect.top = (int) ( ( height - 0 ) - bitmapRect.bottom ); - if ( bitmapRect.left + scrollRect.left >= 0 ) scrollRect.left = (int) ( 0 - bitmapRect.left ); - if ( bitmapRect.right + scrollRect.left <= ( width - 0 ) ) scrollRect.left = (int) ( ( width - 0 ) - bitmapRect.right ); - // Log.d( LOG_TAG, "scrollRect(2): " + scrollRect.toString() ); - } - - protected void scrollBy( float distanceX, float distanceY, final double durationMs ) { - final double dx = distanceX; - final double dy = distanceY; - final long startTime = System.currentTimeMillis(); - mHandler.post( new Runnable() { - - double old_x = 0; - double old_y = 0; - - @Override - public void run() { - long now = System.currentTimeMillis(); - double currentMs = Math.min( durationMs, now - startTime ); - double x = mEasing.easeOut( currentMs, 0, dx, durationMs ); - double y = mEasing.easeOut( currentMs, 0, dy, durationMs ); - panBy( ( x - old_x ), ( y - old_y ) ); - old_x = x; - old_y = y; - if ( currentMs < durationMs ) { - mHandler.post( this ); - } else { - RectF centerRect = getCenter( true, true ); - if ( centerRect.left != 0 || centerRect.top != 0 ) scrollBy( centerRect.left, centerRect.top ); - } - } - } ); - } - - protected void zoomTo( float scale, final float centerX, final float centerY, final float durationMs ) { - // Log.i( LOG_TAG, "zoomTo: " + scale + ", " + centerX + ": " + centerY ); - final long startTime = System.currentTimeMillis(); - final float incrementPerMs = ( scale - getScale() ) / durationMs; - final float oldScale = getScale(); - mHandler.post( new Runnable() { - - @Override - public void run() { - long now = System.currentTimeMillis(); - float currentMs = Math.min( durationMs, now - startTime ); - float target = oldScale + ( incrementPerMs * currentMs ); - zoomTo( target, centerX, centerY ); - if ( currentMs < durationMs ) { - mHandler.post( this ); - } else { - // if ( getScale() < 1f ) {} - } - } - } ); - } - - @Override - public void dispose() { - clear(); - } - - protected void zoomToWidth() { - RectF bitmapRect = getBitmapRect(); - - float w = bitmapRect.right - bitmapRect.left; - - if (w < getWidth()) { - float scale = (float)getWidth() / w; - - zoomTo(scale, 0f, 0f); - } - } -} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Cubic.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Cubic.java deleted file mode 100644 index 6f7e87d..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Cubic.java +++ /dev/null @@ -1,20 +0,0 @@ -package it.sephiroth.android.library.imagezoom.easing; - -public class Cubic implements Easing { - - @Override - public double easeOut( double time, double start, double end, double duration ) { - return end * ( ( time = time / duration - 1.0 ) * time * time + 1.0 ) + start; - } - - @Override - public double easeIn( double time, double start, double end, double duration ) { - return end * ( time /= duration ) * time * time + start; - } - - @Override - public double easeInOut( double time, double start, double end, double duration ) { - if ( ( time /= duration / 2.0 ) < 1.0 ) return end / 2.0 * time * time * time + start; - return end / 2.0 * ( ( time -= 2.0 ) * time * time + 2.0 ) + start; - } -} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Easing.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Easing.java deleted file mode 100644 index 202e9d9..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/easing/Easing.java +++ /dev/null @@ -1,10 +0,0 @@ -package it.sephiroth.android.library.imagezoom.easing; - -public interface Easing { - - double easeOut( double time, double start, double end, double duration ); - - double easeIn( double time, double start, double end, double duration ); - - double easeInOut( double time, double start, double end, double duration ); -} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/FastBitmapDrawable.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/FastBitmapDrawable.java deleted file mode 100644 index 8afc38e..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/FastBitmapDrawable.java +++ /dev/null @@ -1,84 +0,0 @@ -package it.sephiroth.android.library.imagezoom.graphics; - -import java.io.InputStream; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.drawable.Drawable; - -/** - * Fast bitmap drawable. Does not support states. it only - * support alpha and colormatrix - * @author alessandro - * - */ -public class FastBitmapDrawable extends Drawable implements IBitmapDrawable { - - protected Bitmap mBitmap; - protected Paint mPaint; - - public FastBitmapDrawable( Bitmap b ) { - mBitmap = b; - mPaint = new Paint(); - mPaint.setDither( true ); - mPaint.setFilterBitmap( true ); - } - - public FastBitmapDrawable( Resources res, InputStream is ){ - this(BitmapFactory.decodeStream(is)); - } - - @Override - public void draw( Canvas canvas ) { - canvas.drawBitmap( mBitmap, 0.0f, 0.0f, mPaint ); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setAlpha( int alpha ) { - mPaint.setAlpha( alpha ); - } - - @Override - public void setColorFilter( ColorFilter cf ) { - mPaint.setColorFilter( cf ); - } - - @Override - public int getIntrinsicWidth() { - return mBitmap.getWidth(); - } - - @Override - public int getIntrinsicHeight() { - return mBitmap.getHeight(); - } - - @Override - public int getMinimumWidth() { - return mBitmap.getWidth(); - } - - @Override - public int getMinimumHeight() { - return mBitmap.getHeight(); - } - - public void setAntiAlias( boolean value ){ - mPaint.setAntiAlias( value ); - invalidateSelf(); - } - - @Override - public Bitmap getBitmap() { - return mBitmap; - } -} \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/IBitmapDrawable.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/IBitmapDrawable.java deleted file mode 100644 index 5a2892a..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/graphics/IBitmapDrawable.java +++ /dev/null @@ -1,14 +0,0 @@ -package it.sephiroth.android.library.imagezoom.graphics; - -import it.sephiroth.android.library.imagezoom.ImageViewTouchBase; -import android.graphics.Bitmap; - -/** - * Base interface used in the {@link ImageViewTouchBase} view - * @author alessandro - * - */ -public interface IBitmapDrawable { - - Bitmap getBitmap(); -} diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/utils/IDisposable.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/utils/IDisposable.java deleted file mode 100644 index da991a7..0000000 --- a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/utils/IDisposable.java +++ /dev/null @@ -1,6 +0,0 @@ -package it.sephiroth.android.library.imagezoom.utils; - -public interface IDisposable { - - void dispose(); -} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/Application.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/Application.java index 848600f..4095886 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/Application.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/Application.java @@ -1,8 +1,6 @@ package org.fox.ttcomics2; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import com.livefront.bridge.Bridge; import com.livefront.bridge.SavedStateHandler; @@ -11,6 +9,8 @@ import org.acra.ACRA; import org.acra.ReportingInteractionMode; import org.acra.annotation.ReportsCrashes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import icepick.Icepick; @ReportsCrashes(mode = ReportingInteractionMode.SILENT, diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicFragment.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicFragment.java index a21e749..ded84f2 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicFragment.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicFragment.java @@ -5,22 +5,22 @@ import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.v7.app.ActionBar; -import android.view.GestureDetector; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.github.chrisbanes.photoview.OnViewTapListener; +import com.github.chrisbanes.photoview.PhotoView; import org.fox.ttcomics2.archive.ComicArchive; import java.io.IOException; +import androidx.appcompat.app.ActionBar; import icepick.State; -import it.sephiroth.android.library.imagezoom.ImageViewTouch; public class ComicFragment extends StateSavedFragment { private final String TAG = this.getClass().getSimpleName(); @@ -28,9 +28,8 @@ public class ComicFragment extends StateSavedFragment { private SharedPreferences m_prefs; @State protected int m_page; private ViewComicActivity m_activity; - private GestureDetector m_detector; - @State protected boolean m_thumbnail = false; @State protected ComicArchive m_archive; + private PhotoView m_image; public ComicFragment() { super(); @@ -45,147 +44,37 @@ public class ComicFragment extends StateSavedFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_comic, container, false); - - final ImageViewTouch image = view.findViewById(R.id.comic_image); - if (m_prefs.getBoolean("fit_to_width", false)) { - image.setFitToWidth(true); - } else { - image.setFitToScreen(true); - } + m_image = view.findViewById(R.id.comic_image); try { - Glide.with(ComicFragment.this) + Glide.with(getContext()) .load(m_archive.getByteArray(m_page)) .dontAnimate() + .dontTransform() .diskCacheStrategy(DiskCacheStrategy.NONE) .skipMemoryCache(true) - .into(image); + .into(m_image); } catch (IOException e) { - image.setImageResource(R.drawable.badimage); + m_image.setImageResource(R.drawable.badimage); e.printStackTrace(); } - image.setOnScaleChangedListener(new ImageViewTouch.OnScaleChangedListener() { - @Override - public void onScaleChanged(float scale) { - // TODO: shared scale change? - } - }); - - image.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent event) { - return m_detector.onTouchEvent(event); - } - }); - - //} - - return view; - - } - - private void onLeftSideTapped() { - ImageViewTouch image = getView().findViewById(R.id.comic_image); - - if (image != null) { - boolean atLeftEdge = !image.canScroll(1); - - if (atLeftEdge) { - m_activity.selectPreviousComic(); - } - } - } - - private void onRightSideTapped() { - ImageViewTouch image = getView().findViewById(R.id.comic_image); - - if (image != null) { - boolean atRightEdge = !image.canScroll(-1); - - if (atRightEdge) { - m_activity.selectNextComic(); - } + if (m_prefs.getBoolean("fit_to_width", false)) { + m_image.setScaleType(ImageView.ScaleType.CENTER_CROP); } - } - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - - //setThumbnail(!isVisibleToUser); disabled - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - m_prefs = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); - m_activity = (ViewComicActivity) activity; - - m_detector = new GestureDetector(m_activity, new GestureDetector.OnGestureListener() { - - @Override - public boolean onSingleTapUp(MotionEvent e) { - int width = getView().getWidth(); - int x = Math.round(e.getX()); - - if (x <= width/10) { - onLeftSideTapped(); - - return true; - } else if (x >= width-(width/10)) { - onRightSideTapped(); - - return true; - } - - return false; - } - + m_image.setOnViewTapListener(new OnViewTapListener() { @Override - public void onShowPress(MotionEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, - float distanceY) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void onLongPress(MotionEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean onDown(MotionEvent e) { - // TODO Auto-generated method stub - return false; - } - }); - - m_detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - - int width = getView().getWidth(); - int x = Math.round(e.getX()); + public void onViewTap(View view, float x, float y) { + int width = view.getWidth(); boolean fullScreenMode = m_prefs.getBoolean("use_full_screen", false); - if (x > width/10 && x < width-(width/10)) { + if (x <= width / 10) { + m_activity.selectPreviousComic(); + } else if (x > width-(width/10)) { + m_activity.selectNextComic(); + } else { ActionBar bar = m_activity.getSupportActionBar(); if (bar.isShowing()) { @@ -205,24 +94,25 @@ public class ComicFragment extends StateSavedFragment { bar.show(); } - - return true; } - - return false; - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return false; - } - - @Override - public boolean onDoubleTapEvent(MotionEvent e) { - return false; } }); + return view; + + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + m_prefs = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); + m_activity = (ViewComicActivity) activity; } } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java index 96ddf78..f94b14a 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java @@ -4,12 +4,9 @@ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; -import android.graphics.Bitmap; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.BaseColumns; -import android.support.v4.widget.SimpleCursorAdapter; -import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; @@ -18,7 +15,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; @@ -34,6 +30,8 @@ import com.nhaarman.listviewanimations.appearance.simple.ScaleInAnimationAdapter import java.io.File; +import androidx.cursoradapter.widget.SimpleCursorAdapter; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import icepick.State; import jp.co.recruit_mp.android.widget.HeaderFooterGridView; diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java index 08c52ce..738d810 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java @@ -6,10 +6,6 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v7.app.ActionBar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,10 +17,14 @@ import com.ToxicBakery.viewpager.transforms.DepthPageTransformer; import org.fox.ttcomics2.archive.CbrComicArchive; import org.fox.ttcomics2.archive.CbzComicArchive; import org.fox.ttcomics2.archive.ComicArchive; -import org.fox.ttcomics2.utils.IVTViewPager; import java.io.IOException; +import androidx.appcompat.app.ActionBar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.ViewPager; import icepick.State; public class ComicPager extends StateSavedFragment { @@ -84,7 +84,7 @@ public class ComicPager extends StateSavedFragment { } public int getPosition() { - IVTViewPager pager = getView().findViewById(R.id.comics_pager); + ViewPager pager = getView().findViewById(R.id.comics_pager); if (pager != null) { return pager.getCurrentItem(); @@ -94,7 +94,7 @@ public class ComicPager extends StateSavedFragment { } public void setCurrentItem(int item) { - IVTViewPager pager = getView().findViewById(R.id.comics_pager); + ViewPager pager = getView().findViewById(R.id.comics_pager); if (pager != null) { try { @@ -120,7 +120,7 @@ public class ComicPager extends StateSavedFragment { m_adapter = new PagerAdapter(getActivity().getSupportFragmentManager()); - final IVTViewPager pager = view.findViewById(R.id.comics_pager); + final ViewPager pager = view.findViewById(R.id.comics_pager); try { if (m_fileName.toLowerCase().matches(".*\\.(cbz|zip)")) { @@ -187,7 +187,8 @@ public class ComicPager extends StateSavedFragment { e.printStackTrace(); } - pager.setOnPageChangeListener(new IVTViewPager.OnPageChangeListener() { + pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override public void onPageSelected(int position) { m_activity.onComicSelected(m_fileName, position); @@ -200,11 +201,13 @@ public class ComicPager extends StateSavedFragment { hideReadingUI(true); } - + + @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } - + + @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java index f4bbcd8..ede3cd0 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java @@ -7,13 +7,11 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.design.widget.Snackbar; -import android.support.v4.app.JobIntentService; -import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.MenuItem; import android.view.View; +import com.google.android.material.snackbar.Snackbar; import com.livefront.bridge.Bridge; import org.fox.ttcomics2.sync.SyncClient; @@ -23,6 +21,9 @@ import java.io.File; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.JobIntentService; + public class CommonActivity extends AppCompatActivity { private final String TAG = this.getClass().getSimpleName(); diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java index 6a19b63..6a62406 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java @@ -15,13 +15,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.ViewPager; -import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -37,6 +30,13 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.ViewPager; import icepick.State; public class MainActivity extends CommonActivity implements SharedPreferences.OnSharedPreferenceChangeListener { diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PreferencesActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PreferencesActivity.java index d65ec9a..300e369 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PreferencesActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PreferencesActivity.java @@ -5,12 +5,13 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; -import android.support.v7.widget.Toolbar; import android.view.MenuItem; import net.rdrei.android.dirchooser.DirectoryChooserActivity; import net.rdrei.android.dirchooser.DirectoryChooserConfig; +import androidx.appcompat.widget.Toolbar; + public class PreferencesActivity extends CommonActivity { @Override diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/StateSavedFragment.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/StateSavedFragment.java index 023c3dc..840aaf5 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/StateSavedFragment.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/StateSavedFragment.java @@ -1,10 +1,11 @@ package org.fox.ttcomics2; import android.os.Bundle; -import android.support.v4.app.Fragment; import com.livefront.bridge.Bridge; +import androidx.fragment.app.Fragment; + public class StateSavedFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java index 058e091..4733b3f 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java @@ -13,9 +13,6 @@ import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.v4.app.FragmentTransaction; -import android.support.v4.content.FileProvider; -import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -31,6 +28,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.FileProvider; +import androidx.fragment.app.FragmentTransaction; import icepick.State; public class ViewComicActivity extends CommonActivity { diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CacheCleanupService.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CacheCleanupService.java index d68e039..871b026 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CacheCleanupService.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CacheCleanupService.java @@ -2,7 +2,6 @@ package org.fox.ttcomics2.utils; import android.content.Intent; import android.os.Environment; -import android.support.v4.app.JobIntentService; import android.util.Log; import org.fox.ttcomics2.CommonActivity; @@ -12,6 +11,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import androidx.core.app.JobIntentService; + public class CacheCleanupService extends JobIntentService { private final String TAG = this.getClass().getSimpleName(); diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CompatListActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CompatListActivity.java deleted file mode 100644 index 2e04b2a..0000000 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/CompatListActivity.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.fox.ttcomics2.utils; - -import android.support.v7.app.AppCompatActivity; -import android.widget.HeaderViewListAdapter; -import android.widget.ListAdapter; -import android.widget.ListView; - -// http://stackoverflow.com/questions/18403647/actionbaractivity-of-android-support-v7-appcompat-and-listactivity-in-same-act - -public abstract class CompatListActivity extends AppCompatActivity { - - private ListView mListView; - - protected ListView getListView() { - if (mListView == null) { - mListView = (ListView) findViewById(android.R.id.list); - } - return mListView; - } - - protected void setListAdapter(ListAdapter adapter) { - getListView().setAdapter(adapter); - } - - protected ListAdapter getListAdapter() { - ListAdapter adapter = getListView().getAdapter(); - if (adapter instanceof HeaderViewListAdapter) { - return ((HeaderViewListAdapter)adapter).getWrappedAdapter(); - } else { - return adapter; - } - } -} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/IVTViewPager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/IVTViewPager.java deleted file mode 100644 index 814c4f2..0000000 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/utils/IVTViewPager.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.fox.ttcomics2.utils; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -import it.sephiroth.android.library.imagezoom.ImageViewTouch; - -public class IVTViewPager extends android.support.v4.view.ViewPager { - public IVTViewPager(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { - if (v instanceof ImageViewTouch) { - ImageViewTouch ivt = (ImageViewTouch) v; - try { - return ivt.canScroll(dx); - } catch (NullPointerException e) { - // bad image, etc - return false; - } - } else { - return super.canScroll(v, checkV, dx, x, y); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - return super.onTouchEvent(event); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - return super.onInterceptTouchEvent(event); - } -} \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/res/layout/activity_main.xml b/org.fox.ttcomics/src/main/res/layout/activity_main.xml index ad62a46..6a6ddb2 100755 --- a/org.fox.ttcomics/src/main/res/layout/activity_main.xml +++ b/org.fox.ttcomics/src/main/res/layout/activity_main.xml @@ -11,12 +11,12 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - + - - \ No newline at end of file + \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/res/layout/fragment_comic.xml b/org.fox.ttcomics/src/main/res/layout/fragment_comic.xml old mode 100644 new mode 100755 index 55c8513..8364fbd --- a/org.fox.ttcomics/src/main/res/layout/fragment_comic.xml +++ b/org.fox.ttcomics/src/main/res/layout/fragment_comic.xml @@ -1,8 +1,9 @@ - diff --git a/org.fox.ttcomics/src/main/res/layout/fragment_comics_grid.xml b/org.fox.ttcomics/src/main/res/layout/fragment_comics_grid.xml old mode 100644 new mode 100755 index 59d985c..7e34169 --- a/org.fox.ttcomics/src/main/res/layout/fragment_comics_grid.xml +++ b/org.fox.ttcomics/src/main/res/layout/fragment_comics_grid.xml @@ -2,7 +2,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent"> - @@ -13,5 +13,5 @@ android:layout_height="match_parent" android:columnWidth="160dp" android:numColumns="auto_fit" /> - + \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/res/layout/fragment_comics_pager.xml b/org.fox.ttcomics/src/main/res/layout/fragment_comics_pager.xml index 2feda8b..0730abc 100755 --- a/org.fox.ttcomics/src/main/res/layout/fragment_comics_pager.xml +++ b/org.fox.ttcomics/src/main/res/layout/fragment_comics_pager.xml @@ -6,7 +6,7 @@ android:animateLayoutChanges="true" android:layout_height="fill_parent" > - -