parent
92f605bca9
commit
881ece18b2
@ -0,0 +1,60 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.os.Build; |
||||||
|
import android.os.Build.VERSION; |
||||||
|
import android.os.Build.VERSION_CODES; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.view.View; |
||||||
|
|
||||||
|
public 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); |
||||||
|
} |
||||||
|
|
||||||
|
public static int getPointerIndex(int action) { |
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) |
||||||
|
return getPointerIndexHoneyComb(action); |
||||||
|
else |
||||||
|
return getPointerIndexEclair(action); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") |
||||||
|
@TargetApi(Build.VERSION_CODES.ECLAIR) |
||||||
|
private static int getPointerIndexEclair(int action) { |
||||||
|
return (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; |
||||||
|
} |
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB) |
||||||
|
private static int getPointerIndexHoneyComb(int action) { |
||||||
|
return (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
package uk.co.senab.photoview; |
||||||
|
|
||||||
|
import android.graphics.RectF; |
||||||
|
import android.view.GestureDetector; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.widget.ImageView; |
||||||
|
|
||||||
|
/** |
||||||
|
* Provided default implementation of GestureDetector.OnDoubleTapListener, to be overridden with custom behavior, if needed |
||||||
|
* <p> </p> |
||||||
|
* To be used via {@link uk.co.senab.photoview.PhotoViewAttacher#setOnDoubleTapListener(android.view.GestureDetector.OnDoubleTapListener)} |
||||||
|
*/ |
||||||
|
public class DefaultOnDoubleTapListener implements GestureDetector.OnDoubleTapListener { |
||||||
|
|
||||||
|
private PhotoViewAttacher photoViewAttacher; |
||||||
|
|
||||||
|
/** |
||||||
|
* Default constructor |
||||||
|
* |
||||||
|
* @param photoViewAttacher PhotoViewAttacher to bind to |
||||||
|
*/ |
||||||
|
public DefaultOnDoubleTapListener(PhotoViewAttacher photoViewAttacher) { |
||||||
|
setPhotoViewAttacher(photoViewAttacher); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows to change PhotoViewAttacher within range of single instance |
||||||
|
* |
||||||
|
* @param newPhotoViewAttacher PhotoViewAttacher to bind to |
||||||
|
*/ |
||||||
|
public void setPhotoViewAttacher(PhotoViewAttacher newPhotoViewAttacher) { |
||||||
|
this.photoViewAttacher = newPhotoViewAttacher; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onSingleTapConfirmed(MotionEvent e) { |
||||||
|
if (this.photoViewAttacher == null) |
||||||
|
return false; |
||||||
|
|
||||||
|
ImageView imageView = photoViewAttacher.getImageView(); |
||||||
|
|
||||||
|
if (null != photoViewAttacher.getOnPhotoTapListener()) { |
||||||
|
final RectF displayRect = photoViewAttacher.getDisplayRect(); |
||||||
|
|
||||||
|
if (null != displayRect) { |
||||||
|
final float x = e.getX(), y = e.getY(); |
||||||
|
|
||||||
|
// 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(); |
||||||
|
|
||||||
|
photoViewAttacher.getOnPhotoTapListener().onPhotoTap(imageView, xResult, yResult); |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
photoViewAttacher.getOnPhotoTapListener().onOutsidePhotoTap(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (null != photoViewAttacher.getOnViewTapListener()) { |
||||||
|
photoViewAttacher.getOnViewTapListener().onViewTap(imageView, e.getX(), e.getY()); |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onDoubleTap(MotionEvent ev) { |
||||||
|
if (photoViewAttacher == null) |
||||||
|
return false; |
||||||
|
|
||||||
|
try { |
||||||
|
float scale = photoViewAttacher.getScale(); |
||||||
|
float x = ev.getX(); |
||||||
|
float y = ev.getY(); |
||||||
|
|
||||||
|
if (scale < photoViewAttacher.getMediumScale()) { |
||||||
|
photoViewAttacher.setScale(photoViewAttacher.getMediumScale(), x, y, true); |
||||||
|
} else if (scale >= photoViewAttacher.getMediumScale() && scale < photoViewAttacher.getMaximumScale()) { |
||||||
|
photoViewAttacher.setScale(photoViewAttacher.getMaximumScale(), x, y, true); |
||||||
|
} else { |
||||||
|
photoViewAttacher.setScale(photoViewAttacher.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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,285 @@ |
|||||||
|
/** |
||||||
|
* **************************************************************************** |
||||||
|
* Copyright 2011, 2012 Chris Banes. |
||||||
|
* <p> |
||||||
|
* 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 |
||||||
|
* <p> |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p> |
||||||
|
* 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 uk.co.senab.photoview; |
||||||
|
|
||||||
|
import android.graphics.Bitmap; |
||||||
|
import android.graphics.Matrix; |
||||||
|
import android.graphics.RectF; |
||||||
|
import android.view.GestureDetector; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.ImageView; |
||||||
|
|
||||||
|
|
||||||
|
public interface IPhotoView { |
||||||
|
|
||||||
|
float DEFAULT_MAX_SCALE = 3.0f; |
||||||
|
float DEFAULT_MID_SCALE = 1.75f; |
||||||
|
float DEFAULT_MIN_SCALE = 1.0f; |
||||||
|
int DEFAULT_ZOOM_DURATION = 200; |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns true if the PhotoView is set to allow zooming of Photos. |
||||||
|
* |
||||||
|
* @return true if the PhotoView allows zooming. |
||||||
|
*/ |
||||||
|
boolean canZoom(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the Display Rectangle of the currently displayed Drawable. The Rectangle is relative to |
||||||
|
* this View and includes all scaling and translations. |
||||||
|
* |
||||||
|
* @return - RectF of Displayed Drawable |
||||||
|
*/ |
||||||
|
RectF getDisplayRect(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the Display Matrix of the currently displayed Drawable. The Rectangle is considered |
||||||
|
* relative to this View and includes all scaling and translations. |
||||||
|
* |
||||||
|
* @param finalMatrix target matrix to set PhotoView to |
||||||
|
* @return - true if rectangle was applied successfully |
||||||
|
*/ |
||||||
|
boolean setDisplayMatrix(Matrix finalMatrix); |
||||||
|
|
||||||
|
/** |
||||||
|
* Copies the Display Matrix of the currently displayed Drawable. The Rectangle is considered |
||||||
|
* relative to this View and includes all scaling and translations. |
||||||
|
* |
||||||
|
* @param matrix target matrix to copy to |
||||||
|
*/ |
||||||
|
void getDisplayMatrix(Matrix matrix); |
||||||
|
|
||||||
|
/** |
||||||
|
* @return The current minimum scale level. What this value represents depends on the current |
||||||
|
* {@link android.widget.ImageView.ScaleType}. |
||||||
|
*/ |
||||||
|
float getMinimumScale(); |
||||||
|
|
||||||
|
/** |
||||||
|
* @return The current medium scale level. What this value represents depends on the current |
||||||
|
* {@link android.widget.ImageView.ScaleType}. |
||||||
|
*/ |
||||||
|
float getMediumScale(); |
||||||
|
|
||||||
|
/** |
||||||
|
* @return The current maximum scale level. What this value represents depends on the current |
||||||
|
* {@link android.widget.ImageView.ScaleType}. |
||||||
|
*/ |
||||||
|
float getMaximumScale(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the current scale value |
||||||
|
* |
||||||
|
* @return float - current scale value |
||||||
|
*/ |
||||||
|
float getScale(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the current scale type in use by the ImageView. |
||||||
|
* |
||||||
|
* @return current ImageView.ScaleType |
||||||
|
*/ |
||||||
|
ImageView.ScaleType getScaleType(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll |
||||||
|
* to it's horizontal edge. |
||||||
|
* |
||||||
|
* @param allow whether to allow intercepting by parent element or not |
||||||
|
*/ |
||||||
|
void setAllowParentInterceptOnEdge(boolean allow); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the minimum scale level. What this value represents depends on the current {@link |
||||||
|
* android.widget.ImageView.ScaleType}. |
||||||
|
* |
||||||
|
* @param minimumScale minimum allowed scale |
||||||
|
*/ |
||||||
|
void setMinimumScale(float minimumScale); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the medium scale level. What this value represents depends on the current {@link android.widget.ImageView.ScaleType}. |
||||||
|
* |
||||||
|
* @param mediumScale medium scale preset |
||||||
|
*/ |
||||||
|
void setMediumScale(float mediumScale); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the maximum scale level. What this value represents depends on the current {@link |
||||||
|
* android.widget.ImageView.ScaleType}. |
||||||
|
* |
||||||
|
* @param maximumScale maximum allowed scale preset |
||||||
|
*/ |
||||||
|
void setMaximumScale(float maximumScale); |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows to set all three scale levels at once, so you don't run into problem with setting |
||||||
|
* medium/minimum scale before the maximum one |
||||||
|
* |
||||||
|
* @param minimumScale minimum allowed scale |
||||||
|
* @param mediumScale medium allowed scale |
||||||
|
* @param maximumScale maximum allowed scale preset |
||||||
|
*/ |
||||||
|
void setScaleLevels(float minimumScale, float mediumScale, float maximumScale); |
||||||
|
|
||||||
|
/** |
||||||
|
* Register a callback to be invoked when the Photo displayed by this view is long-pressed. |
||||||
|
* |
||||||
|
* @param listener - Listener to be registered. |
||||||
|
*/ |
||||||
|
void setOnLongClickListener(View.OnLongClickListener listener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Register a callback to be invoked when the Matrix has changed for this View. An example would |
||||||
|
* be the user panning or scaling the Photo. |
||||||
|
* |
||||||
|
* @param listener - Listener to be registered. |
||||||
|
*/ |
||||||
|
void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Register a callback to be invoked when the Photo displayed by this View is tapped with a |
||||||
|
* single tap. |
||||||
|
* |
||||||
|
* @param listener - Listener to be registered. |
||||||
|
*/ |
||||||
|
void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Register a callback to be invoked when the View is tapped with a single tap. |
||||||
|
* |
||||||
|
* @param onRotateListener |
||||||
|
*/ |
||||||
|
void setOnRotateListener(PhotoViewAttacher.OnRotateListener onRotateListener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Enables rotation via PhotoView internal functions. |
||||||
|
* |
||||||
|
* @param rotationDegree - Degree to rotate PhotoView to, should be in range 0 to 360 |
||||||
|
*/ |
||||||
|
void setRotationTo(float rotationDegree); |
||||||
|
|
||||||
|
/** |
||||||
|
* Enables rotation via PhotoView internal functions. |
||||||
|
* |
||||||
|
* @param rotationDegree - Degree to rotate PhotoView by, should be in range 0 to 360 |
||||||
|
*/ |
||||||
|
void setRotationBy(float rotationDegree); |
||||||
|
|
||||||
|
/** |
||||||
|
* Changes the current scale to the specified value. |
||||||
|
* |
||||||
|
* @param scale - Value to scale to |
||||||
|
*/ |
||||||
|
void setScale(float scale); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a callback listener to be invoked when the View is tapped with a single tap. |
||||||
|
* |
||||||
|
* @return PhotoViewAttacher.OnViewTapListener currently set, may be null |
||||||
|
*/ |
||||||
|
PhotoViewAttacher.OnViewTapListener getOnViewTapListener(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Register a callback to be invoked when the View is tapped with a single tap. |
||||||
|
* |
||||||
|
* @param listener - Listener to be registered. |
||||||
|
*/ |
||||||
|
void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Changes the current scale to the specified value. |
||||||
|
* |
||||||
|
* @param scale - Value to scale to |
||||||
|
* @param animate - Whether to animate the scale |
||||||
|
*/ |
||||||
|
void setScale(float scale, boolean animate); |
||||||
|
|
||||||
|
/** |
||||||
|
* Changes the current scale to the specified value, around the given focal point. |
||||||
|
* |
||||||
|
* @param scale - Value to scale to |
||||||
|
* @param focalX - X Focus Point |
||||||
|
* @param focalY - Y Focus Point |
||||||
|
* @param animate - Whether to animate the scale |
||||||
|
*/ |
||||||
|
void setScale(float scale, float focalX, float focalY, boolean animate); |
||||||
|
|
||||||
|
/** |
||||||
|
* Controls how the image should be resized or moved to match the size of the ImageView. Any |
||||||
|
* scaling or panning will happen within the confines of this {@link |
||||||
|
* android.widget.ImageView.ScaleType}. |
||||||
|
* |
||||||
|
* @param scaleType - The desired scaling mode. |
||||||
|
*/ |
||||||
|
void setScaleType(ImageView.ScaleType scaleType); |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows you to enable/disable the zoom functionality on the ImageView. When disable the |
||||||
|
* ImageView reverts to using the FIT_CENTER matrix. |
||||||
|
* |
||||||
|
* @param zoomable - Whether the zoom functionality is enabled. |
||||||
|
*/ |
||||||
|
void setZoomable(boolean zoomable); |
||||||
|
|
||||||
|
/** |
||||||
|
* Extracts currently visible area to Bitmap object, if there is no image loaded yet or the |
||||||
|
* ImageView is already destroyed, returns {@code null} |
||||||
|
* |
||||||
|
* @return currently visible area as bitmap or null |
||||||
|
*/ |
||||||
|
Bitmap getVisibleRectangleBitmap(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows to change zoom transition speed, default value is 200 (PhotoViewAttacher.DEFAULT_ZOOM_DURATION). |
||||||
|
* Will default to 200 if provided negative value |
||||||
|
* |
||||||
|
* @param milliseconds duration of zoom interpolation |
||||||
|
*/ |
||||||
|
void setZoomTransitionDuration(int milliseconds); |
||||||
|
|
||||||
|
/** |
||||||
|
* Will return instance of IPhotoView (eg. PhotoViewAttacher), can be used to provide better |
||||||
|
* integration |
||||||
|
* |
||||||
|
* @return IPhotoView implementation instance if available, null if not |
||||||
|
*/ |
||||||
|
IPhotoView getIPhotoViewImplementation(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets custom double tap listener, to intercept default given functions. To reset behavior to |
||||||
|
* default, you can just pass in "null" or public field of PhotoViewAttacher.defaultOnDoubleTapListener |
||||||
|
* |
||||||
|
* @param newOnDoubleTapListener custom OnDoubleTapListener to be set on ImageView |
||||||
|
*/ |
||||||
|
void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Will report back about scale changes |
||||||
|
* |
||||||
|
* @param onScaleChangeListener OnScaleChangeListener instance |
||||||
|
*/ |
||||||
|
void setOnScaleChangeListener(PhotoViewAttacher.OnScaleChangeListener onScaleChangeListener); |
||||||
|
|
||||||
|
/** |
||||||
|
* Will report back about fling(single touch) |
||||||
|
* |
||||||
|
* @param onSingleFlingListener OnSingleFlingListener instance |
||||||
|
*/ |
||||||
|
void setOnSingleFlingListener(PhotoViewAttacher.OnSingleFlingListener onSingleFlingListener); |
||||||
|
} |
@ -0,0 +1,284 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.graphics.Bitmap; |
||||||
|
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; |
||||||
|
import uk.co.senab.photoview.PhotoViewAttacher.OnMatrixChangedListener; |
||||||
|
import uk.co.senab.photoview.PhotoViewAttacher.OnPhotoTapListener; |
||||||
|
import uk.co.senab.photoview.PhotoViewAttacher.OnViewTapListener; |
||||||
|
|
||||||
|
public class PhotoView extends AppCompatImageView implements IPhotoView { |
||||||
|
|
||||||
|
private PhotoViewAttacher mAttacher; |
||||||
|
|
||||||
|
private ScaleType mPendingScaleType; |
||||||
|
|
||||||
|
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); |
||||||
|
super.setScaleType(ScaleType.MATRIX); |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
protected void init() { |
||||||
|
if (null == mAttacher || null == mAttacher.getImageView()) { |
||||||
|
mAttacher = new PhotoViewAttacher(this); |
||||||
|
} |
||||||
|
|
||||||
|
if (null != mPendingScaleType) { |
||||||
|
setScaleType(mPendingScaleType); |
||||||
|
mPendingScaleType = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setRotationTo(float rotationDegree) { |
||||||
|
mAttacher.setRotationTo(rotationDegree); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setRotationBy(float rotationDegree) { |
||||||
|
mAttacher.setRotationBy(rotationDegree); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canZoom() { |
||||||
|
return mAttacher.canZoom(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RectF getDisplayRect() { |
||||||
|
return mAttacher.getDisplayRect(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void getDisplayMatrix(Matrix matrix) { |
||||||
|
mAttacher.getDisplayMatrix(matrix); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean setDisplayMatrix(Matrix finalRectangle) { |
||||||
|
return mAttacher.setDisplayMatrix(finalRectangle); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public float getMinimumScale() { |
||||||
|
return mAttacher.getMinimumScale(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public float getMediumScale() { |
||||||
|
return mAttacher.getMediumScale(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public float getMaximumScale() { |
||||||
|
return mAttacher.getMaximumScale(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public float getScale() { |
||||||
|
return mAttacher.getScale(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ScaleType getScaleType() { |
||||||
|
return mAttacher.getScaleType(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Matrix getImageMatrix() { |
||||||
|
return mAttacher.getImageMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setAllowParentInterceptOnEdge(boolean allow) { |
||||||
|
mAttacher.setAllowParentInterceptOnEdge(allow); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setMinimumScale(float minimumScale) { |
||||||
|
mAttacher.setMinimumScale(minimumScale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setMediumScale(float mediumScale) { |
||||||
|
mAttacher.setMediumScale(mediumScale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setMaximumScale(float maximumScale) { |
||||||
|
mAttacher.setMaximumScale(maximumScale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) { |
||||||
|
mAttacher.setScaleLevels(minimumScale, mediumScale, maximumScale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
// setImageBitmap calls through to this method
|
||||||
|
public void setImageDrawable(Drawable drawable) { |
||||||
|
super.setImageDrawable(drawable); |
||||||
|
if (null != mAttacher) { |
||||||
|
mAttacher.update(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setImageResource(int resId) { |
||||||
|
super.setImageResource(resId); |
||||||
|
if (null != mAttacher) { |
||||||
|
mAttacher.update(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setImageURI(Uri uri) { |
||||||
|
super.setImageURI(uri); |
||||||
|
if (null != mAttacher) { |
||||||
|
mAttacher.update(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean setFrame(int l, int t, int r, int b) { |
||||||
|
boolean changed = super.setFrame(l, t, r, b); |
||||||
|
if (null != mAttacher) { |
||||||
|
mAttacher.update(); |
||||||
|
} |
||||||
|
return changed; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnMatrixChangeListener(OnMatrixChangedListener listener) { |
||||||
|
mAttacher.setOnMatrixChangeListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnLongClickListener(OnLongClickListener l) { |
||||||
|
mAttacher.setOnLongClickListener(l); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnPhotoTapListener(OnPhotoTapListener listener) { |
||||||
|
mAttacher.setOnPhotoTapListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnRotateListener(PhotoViewAttacher.OnRotateListener onRotateListener) { |
||||||
|
mAttacher.setOnRotateListener(onRotateListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OnViewTapListener getOnViewTapListener() { |
||||||
|
return mAttacher.getOnViewTapListener(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnViewTapListener(OnViewTapListener listener) { |
||||||
|
mAttacher.setOnViewTapListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setScale(float scale) { |
||||||
|
mAttacher.setScale(scale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setScale(float scale, boolean animate) { |
||||||
|
mAttacher.setScale(scale, animate); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setScale(float scale, float focalX, float focalY, boolean animate) { |
||||||
|
mAttacher.setScale(scale, focalX, focalY, animate); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setScaleType(ScaleType scaleType) { |
||||||
|
if (null != mAttacher) { |
||||||
|
mAttacher.setScaleType(scaleType); |
||||||
|
} else { |
||||||
|
mPendingScaleType = scaleType; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setZoomable(boolean zoomable) { |
||||||
|
mAttacher.setZoomable(zoomable); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Bitmap getVisibleRectangleBitmap() { |
||||||
|
return mAttacher.getVisibleRectangleBitmap(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setZoomTransitionDuration(int milliseconds) { |
||||||
|
mAttacher.setZoomTransitionDuration(milliseconds); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public IPhotoView getIPhotoViewImplementation() { |
||||||
|
return mAttacher; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) { |
||||||
|
mAttacher.setOnDoubleTapListener(newOnDoubleTapListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnScaleChangeListener(PhotoViewAttacher.OnScaleChangeListener onScaleChangeListener) { |
||||||
|
mAttacher.setOnScaleChangeListener(onScaleChangeListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnSingleFlingListener(PhotoViewAttacher.OnSingleFlingListener onSingleFlingListener) { |
||||||
|
mAttacher.setOnSingleFlingListener(onSingleFlingListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onDetachedFromWindow() { |
||||||
|
mAttacher.cleanup(); |
||||||
|
mAttacher = null; |
||||||
|
super.onDetachedFromWindow(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onAttachedToWindow() { |
||||||
|
init(); |
||||||
|
super.onAttachedToWindow(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,149 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.view.VelocityTracker; |
||||||
|
import android.view.ViewConfiguration; |
||||||
|
|
||||||
|
import uk.co.senab.photoview.log.LogManager; |
||||||
|
|
||||||
|
public class CupcakeGestureDetector implements GestureDetector { |
||||||
|
|
||||||
|
protected OnGestureListener mListener; |
||||||
|
private static final String LOG_TAG = "CupcakeGestureDetector"; |
||||||
|
float mLastTouchX; |
||||||
|
float mLastTouchY; |
||||||
|
final float mTouchSlop; |
||||||
|
final float mMinimumVelocity; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setOnGestureListener(OnGestureListener listener) { |
||||||
|
this.mListener = listener; |
||||||
|
} |
||||||
|
|
||||||
|
public CupcakeGestureDetector(Context context) { |
||||||
|
final ViewConfiguration configuration = ViewConfiguration |
||||||
|
.get(context); |
||||||
|
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); |
||||||
|
mTouchSlop = configuration.getScaledTouchSlop(); |
||||||
|
} |
||||||
|
|
||||||
|
private VelocityTracker mVelocityTracker; |
||||||
|
private boolean mIsDragging; |
||||||
|
|
||||||
|
float getActiveX(MotionEvent ev) { |
||||||
|
return ev.getX(); |
||||||
|
} |
||||||
|
|
||||||
|
float getActiveY(MotionEvent ev) { |
||||||
|
return ev.getY(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isScaling() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isDragging() { |
||||||
|
return mIsDragging; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onTouchEvent(MotionEvent ev) { |
||||||
|
switch (ev.getAction()) { |
||||||
|
case MotionEvent.ACTION_DOWN: { |
||||||
|
mVelocityTracker = VelocityTracker.obtain(); |
||||||
|
if (null != mVelocityTracker) { |
||||||
|
mVelocityTracker.addMovement(ev); |
||||||
|
} else { |
||||||
|
LogManager.getLogger().i(LOG_TAG, "Velocity tracker is null"); |
||||||
|
} |
||||||
|
|
||||||
|
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: { |
||||||
|
// Recycle Velocity Tracker
|
||||||
|
if (null != mVelocityTracker) { |
||||||
|
mVelocityTracker.recycle(); |
||||||
|
mVelocityTracker = null; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP: { |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
/** |
||||||
|
* **************************************************************************** |
||||||
|
* Copyright 2011, 2012 Chris Banes. |
||||||
|
* <p> |
||||||
|
* 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 |
||||||
|
* <p> |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p> |
||||||
|
* 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 uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.content.Context; |
||||||
|
import android.view.MotionEvent; |
||||||
|
|
||||||
|
import uk.co.senab.photoview.Compat; |
||||||
|
|
||||||
|
@TargetApi(5) |
||||||
|
public class EclairGestureDetector extends CupcakeGestureDetector { |
||||||
|
|
||||||
|
private static final int INVALID_POINTER_ID = -1; |
||||||
|
private int mActivePointerId = INVALID_POINTER_ID; |
||||||
|
private int mActivePointerIndex = 0; |
||||||
|
|
||||||
|
public EclairGestureDetector(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
float getActiveX(MotionEvent ev) { |
||||||
|
try { |
||||||
|
return ev.getX(mActivePointerIndex); |
||||||
|
} catch (Exception e) { |
||||||
|
return ev.getX(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
float getActiveY(MotionEvent ev) { |
||||||
|
try { |
||||||
|
return ev.getY(mActivePointerIndex); |
||||||
|
} catch (Exception e) { |
||||||
|
return ev.getY(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onTouchEvent(MotionEvent ev) { |
||||||
|
final int action = ev.getAction(); |
||||||
|
switch (action & MotionEvent.ACTION_MASK) { |
||||||
|
case MotionEvent.ACTION_DOWN: |
||||||
|
mActivePointerId = ev.getPointerId(0); |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_CANCEL: |
||||||
|
case MotionEvent.ACTION_UP: |
||||||
|
mActivePointerId = INVALID_POINTER_ID; |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_POINTER_UP: |
||||||
|
// Ignore deprecation, ACTION_POINTER_ID_MASK and
|
||||||
|
// ACTION_POINTER_ID_SHIFT has same value and are deprecated
|
||||||
|
// You can have either deprecation or lint target api warning
|
||||||
|
final int pointerIndex = Compat.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); |
||||||
|
try { |
||||||
|
return super.onTouchEvent(ev); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
// Fix for support lib bug, happening when onDestroy is
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* Copyright 2011, 2012 Chris Banes. |
||||||
|
* <p/> |
||||||
|
* 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 |
||||||
|
* <p/> |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p/> |
||||||
|
* 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 uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.content.Context; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.view.ScaleGestureDetector; |
||||||
|
|
||||||
|
@TargetApi(8) |
||||||
|
public class FroyoGestureDetector extends EclairGestureDetector { |
||||||
|
|
||||||
|
protected final ScaleGestureDetector mDetector; |
||||||
|
|
||||||
|
public FroyoGestureDetector(Context context) { |
||||||
|
super(context); |
||||||
|
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; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isScaling() { |
||||||
|
return mDetector.isInProgress(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onTouchEvent(MotionEvent ev) { |
||||||
|
try { |
||||||
|
mDetector.onTouchEvent(ev); |
||||||
|
return super.onTouchEvent(ev); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
// Fix for support lib bug, happening when onDestroy is
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.view.MotionEvent; |
||||||
|
|
||||||
|
public interface GestureDetector { |
||||||
|
|
||||||
|
boolean onTouchEvent(MotionEvent ev); |
||||||
|
|
||||||
|
boolean isScaling(); |
||||||
|
|
||||||
|
boolean isDragging(); |
||||||
|
|
||||||
|
void setOnGestureListener(OnGestureListener listener); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.view.MotionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface to detect rotation |
||||||
|
* Created by ChenSL on 2015/9/16. |
||||||
|
*/ |
||||||
|
public interface IRotateDetector { |
||||||
|
/** |
||||||
|
* handle rotation in onTouchEvent |
||||||
|
* |
||||||
|
* @param event The motion event. |
||||||
|
* @return True if the event was handled, false otherwise. |
||||||
|
*/ |
||||||
|
boolean onTouchEvent(MotionEvent event); |
||||||
|
|
||||||
|
/** |
||||||
|
* is the Gesture Rotate |
||||||
|
* |
||||||
|
* @return true:rotating;false,otherwise |
||||||
|
*/ |
||||||
|
boolean isRotating(); |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface for a callback for rotation |
||||||
|
* Created by ChenSL on 2015/9/16. |
||||||
|
*/ |
||||||
|
public interface IRotateListener { |
||||||
|
/** |
||||||
|
* callback for rotation |
||||||
|
* |
||||||
|
* @param degree degree of rotation |
||||||
|
*/ |
||||||
|
void rotate(int degree, int pivotX, int pivotY); |
||||||
|
|
||||||
|
/** |
||||||
|
* MotionEvent.ACTION_POINTER_UP happens when two finger minus to only one |
||||||
|
* change the ImageView to 0,90,180,270 |
||||||
|
*/ |
||||||
|
void upRotate(int pivotX, int pivotY); |
||||||
|
} |
@ -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 uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
public 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); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
package uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
import android.view.MotionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* Handle ImageView rotate event with two fingers |
||||||
|
* Created by ChenSL on 2015/9/16. |
||||||
|
*/ |
||||||
|
public class RotateGestureDetector implements IRotateDetector { |
||||||
|
private int mLastAngle = 0; |
||||||
|
private IRotateListener mListener; |
||||||
|
private boolean mIsRotate; |
||||||
|
|
||||||
|
/** |
||||||
|
* set rotation listener for callback |
||||||
|
* |
||||||
|
* @param listener a rotation listener |
||||||
|
*/ |
||||||
|
public void setRotateListener(IRotateListener listener) { |
||||||
|
this.mListener = listener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onTouchEvent(MotionEvent event) { |
||||||
|
return doRotate(event); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isRotating() { |
||||||
|
return mIsRotate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* handle rotation |
||||||
|
* |
||||||
|
* @param ev Motion event |
||||||
|
* @return always true. |
||||||
|
*/ |
||||||
|
private boolean doRotate(MotionEvent ev) { |
||||||
|
if (ev.getPointerCount() != 2) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
//Calculate the angle between the two fingers
|
||||||
|
int pivotX = (int) (ev.getX(0) + ev.getX(1)) / 2; |
||||||
|
int pivotY = (int) (ev.getY(0) + ev.getY(1)) / 2; |
||||||
|
float deltaX = ev.getX(0) - ev.getX(1); |
||||||
|
float deltaY = ev.getY(0) - ev.getY(1); |
||||||
|
double radians = Math.atan(deltaY / deltaX); |
||||||
|
//Convert to degrees
|
||||||
|
int degrees = (int) (radians * 180 / Math.PI); |
||||||
|
/* |
||||||
|
* Must use getActionMasked() for switching to pick up pointer events. |
||||||
|
* These events have the pointer index encoded in them so the return |
||||||
|
* from getAction() won't match the exact action constant. |
||||||
|
*/ |
||||||
|
switch (ev.getActionMasked()) { |
||||||
|
case MotionEvent.ACTION_DOWN: |
||||||
|
mLastAngle = degrees; |
||||||
|
mIsRotate = false; |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_UP: |
||||||
|
mIsRotate = false; |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_POINTER_DOWN: |
||||||
|
mLastAngle = degrees; |
||||||
|
mIsRotate = false; |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_CANCEL: |
||||||
|
case MotionEvent.ACTION_POINTER_UP: |
||||||
|
mIsRotate = false; |
||||||
|
upRotate(pivotX, pivotY); |
||||||
|
mLastAngle = degrees; |
||||||
|
break; |
||||||
|
case MotionEvent.ACTION_MOVE: |
||||||
|
mIsRotate = true; |
||||||
|
int degreesValue = degrees - mLastAngle; |
||||||
|
if (degreesValue > 45) { |
||||||
|
//Going CCW across the boundary
|
||||||
|
rotate(-5, pivotX, pivotY); |
||||||
|
} else if (degreesValue < -45) { |
||||||
|
//Going CW across the boundary
|
||||||
|
rotate(5, pivotX, pivotY); |
||||||
|
} else { |
||||||
|
//Normal rotation, rotate the difference
|
||||||
|
rotate(degreesValue, pivotX, pivotY); |
||||||
|
} |
||||||
|
//Save the current angle
|
||||||
|
mLastAngle = degrees; |
||||||
|
break; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* to invoke the callback |
||||||
|
* |
||||||
|
* @param degree degree to rotate |
||||||
|
*/ |
||||||
|
private void rotate(int degree, int pivotX, int pivotY) { |
||||||
|
if (mListener != null) { |
||||||
|
mListener.rotate(degree, pivotX, pivotY); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* to invoke the finger up action |
||||||
|
*/ |
||||||
|
private void upRotate(int pivotX, int pivotY) { |
||||||
|
if (mListener != null) { |
||||||
|
mListener.upRotate(pivotX, pivotY); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package uk.co.senab.photoview.gestures; |
||||||
|
|
||||||
|
/******************************************************************************* |
||||||
|
* 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. |
||||||
|
*******************************************************************************/ |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.os.Build; |
||||||
|
|
||||||
|
public final class VersionedGestureDetector { |
||||||
|
|
||||||
|
public static GestureDetector newInstance(Context context, |
||||||
|
OnGestureListener listener) { |
||||||
|
final int sdkVersion = Build.VERSION.SDK_INT; |
||||||
|
GestureDetector detector; |
||||||
|
|
||||||
|
if (sdkVersion < Build.VERSION_CODES.ECLAIR) { |
||||||
|
detector = new CupcakeGestureDetector(context); |
||||||
|
} else if (sdkVersion < Build.VERSION_CODES.FROYO) { |
||||||
|
detector = new EclairGestureDetector(context); |
||||||
|
} else { |
||||||
|
detector = new FroyoGestureDetector(context); |
||||||
|
} |
||||||
|
|
||||||
|
detector.setOnGestureListener(listener); |
||||||
|
|
||||||
|
return detector; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.log; |
||||||
|
|
||||||
|
import android.util.Log; |
||||||
|
|
||||||
|
/** |
||||||
|
* class that holds the {@link Logger} for this library, defaults to {@link LoggerDefault} to send logs to android {@link Log} |
||||||
|
*/ |
||||||
|
public final class LogManager { |
||||||
|
|
||||||
|
private static Logger logger = new LoggerDefault(); |
||||||
|
|
||||||
|
public static void setLogger(Logger newLogger) { |
||||||
|
logger = newLogger; |
||||||
|
} |
||||||
|
|
||||||
|
public static Logger getLogger() { |
||||||
|
return logger; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,116 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.log; |
||||||
|
|
||||||
|
/** |
||||||
|
* interface for a logger class to replace the static calls to {@link android.util.Log} |
||||||
|
*/ |
||||||
|
public interface Logger { |
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#VERBOSE} log message. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
*/ |
||||||
|
int v(String tag, String msg); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#VERBOSE} log message and log the exception. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
* @param tr An exception to log |
||||||
|
*/ |
||||||
|
int v(String tag, String msg, Throwable tr); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#DEBUG} log message. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
*/ |
||||||
|
int d(String tag, String msg); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#DEBUG} log message and log the exception. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
* @param tr An exception to log |
||||||
|
*/ |
||||||
|
int d(String tag, String msg, Throwable tr); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send an {@link android.util.Log#INFO} log message. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
*/ |
||||||
|
int i(String tag, String msg); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#INFO} log message and log the exception. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
* @param tr An exception to log |
||||||
|
*/ |
||||||
|
int i(String tag, String msg, Throwable tr); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#WARN} log message. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
*/ |
||||||
|
int w(String tag, String msg); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#WARN} log message and log the exception. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
* @param tr An exception to log |
||||||
|
*/ |
||||||
|
int w(String tag, String msg, Throwable tr); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send an {@link android.util.Log#ERROR} log message. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
*/ |
||||||
|
int e(String tag, String msg); |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a {@link android.util.Log#ERROR} log message and log the exception. |
||||||
|
* |
||||||
|
* @param tag Used to identify the source of a log message. It usually identifies |
||||||
|
* the class or activity where the log call occurs. |
||||||
|
* @param msg The message you would like logged. |
||||||
|
* @param tr An exception to log |
||||||
|
*/ |
||||||
|
int e(String tag, String msg, Throwable tr); |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.log; |
||||||
|
|
||||||
|
import android.util.Log; |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper class to redirect {@link LogManager#logger} to {@link Log} |
||||||
|
*/ |
||||||
|
public class LoggerDefault implements Logger { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int v(String tag, String msg) { |
||||||
|
return Log.v(tag, msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int v(String tag, String msg, Throwable tr) { |
||||||
|
return Log.v(tag, msg, tr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int d(String tag, String msg) { |
||||||
|
return Log.d(tag, msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int d(String tag, String msg, Throwable tr) { |
||||||
|
return Log.d(tag, msg, tr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int i(String tag, String msg) { |
||||||
|
return Log.i(tag, msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int i(String tag, String msg, Throwable tr) { |
||||||
|
return Log.i(tag, msg, tr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int w(String tag, String msg) { |
||||||
|
return Log.w(tag, msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int w(String tag, String msg, Throwable tr) { |
||||||
|
return Log.w(tag, msg, tr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int e(String tag, String msg) { |
||||||
|
return Log.e(tag, msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int e(String tag, String msg, Throwable tr) { |
||||||
|
return Log.e(tag, msg, tr); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.scrollerproxy; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.content.Context; |
||||||
|
import android.widget.OverScroller; |
||||||
|
|
||||||
|
@TargetApi(9) |
||||||
|
public class GingerScroller extends ScrollerProxy { |
||||||
|
|
||||||
|
protected final OverScroller mScroller; |
||||||
|
|
||||||
|
public GingerScroller(Context context) { |
||||||
|
mScroller = new OverScroller(context); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean computeScrollOffset() { |
||||||
|
return mScroller.computeScrollOffset(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY, |
||||||
|
int overX, int overY) { |
||||||
|
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void forceFinished(boolean finished) { |
||||||
|
mScroller.forceFinished(finished); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isFinished() { |
||||||
|
return mScroller.isFinished(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCurrX() { |
||||||
|
return mScroller.getCurrX(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCurrY() { |
||||||
|
return mScroller.getCurrY(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.scrollerproxy; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.content.Context; |
||||||
|
|
||||||
|
@TargetApi(14) |
||||||
|
public class IcsScroller extends GingerScroller { |
||||||
|
|
||||||
|
public IcsScroller(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean computeScrollOffset() { |
||||||
|
return mScroller.computeScrollOffset(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.scrollerproxy; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.widget.Scroller; |
||||||
|
|
||||||
|
public class PreGingerScroller extends ScrollerProxy { |
||||||
|
|
||||||
|
private final Scroller mScroller; |
||||||
|
|
||||||
|
public PreGingerScroller(Context context) { |
||||||
|
mScroller = new Scroller(context); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean computeScrollOffset() { |
||||||
|
return mScroller.computeScrollOffset(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY, |
||||||
|
int overX, int overY) { |
||||||
|
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void forceFinished(boolean finished) { |
||||||
|
mScroller.forceFinished(finished); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isFinished() { |
||||||
|
return mScroller.isFinished(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCurrX() { |
||||||
|
return mScroller.getCurrX(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCurrY() { |
||||||
|
return mScroller.getCurrY(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/******************************************************************************* |
||||||
|
* 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 uk.co.senab.photoview.scrollerproxy; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.os.Build.VERSION; |
||||||
|
import android.os.Build.VERSION_CODES; |
||||||
|
|
||||||
|
public abstract class ScrollerProxy { |
||||||
|
|
||||||
|
public static ScrollerProxy getScroller(Context context) { |
||||||
|
if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) { |
||||||
|
return new PreGingerScroller(context); |
||||||
|
} else if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) { |
||||||
|
return new GingerScroller(context); |
||||||
|
} else { |
||||||
|
return new IcsScroller(context); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract boolean computeScrollOffset(); |
||||||
|
|
||||||
|
public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, |
||||||
|
int maxY, int overX, int overY); |
||||||
|
|
||||||
|
public abstract void forceFinished(boolean finished); |
||||||
|
|
||||||
|
public abstract boolean isFinished(); |
||||||
|
|
||||||
|
public abstract int getCurrX(); |
||||||
|
|
||||||
|
public abstract int getCurrY(); |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
<resources> |
||||||
|
<!-- Default screen margins, per the Android Design guidelines. --> |
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen> |
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen> |
||||||
|
</resources> |
@ -0,0 +1,3 @@ |
|||||||
|
<resources> |
||||||
|
<string name="hello_world">Hello world!</string> |
||||||
|
</resources> |
@ -1,3 +1,3 @@ |
|||||||
## 二维码扫描库 |
# 二维码扫描库 |
||||||
|
|
||||||
修改自 [BGAQRCode-Android](https://github.com/bingoogolapple/BGAQRCode-Android) |
修改自 [BGAQRCode-Android](https://github.com/bingoogolapple/BGAQRCode-Android) |
Binary file not shown.
@ -1,4 +1,4 @@ |
|||||||
package com.android.sdk.qrcode.zxing; |
package com.android.sdk.qrcode; |
||||||
|
|
||||||
import android.graphics.Bitmap; |
import android.graphics.Bitmap; |
||||||
import android.graphics.BitmapFactory; |
import android.graphics.BitmapFactory; |
@ -1,4 +1,4 @@ |
|||||||
package com.android.sdk.qrcode.zxing; |
package com.android.sdk.qrcode; |
||||||
|
|
||||||
import android.graphics.Bitmap; |
import android.graphics.Bitmap; |
||||||
import android.graphics.Canvas; |
import android.graphics.Canvas; |
@ -1,11 +1,9 @@ |
|||||||
package com.android.sdk.qrcode.zxing; |
package com.android.sdk.qrcode; |
||||||
|
|
||||||
import android.content.Context; |
import android.content.Context; |
||||||
import android.graphics.Rect; |
import android.graphics.Rect; |
||||||
import android.util.AttributeSet; |
import android.util.AttributeSet; |
||||||
|
|
||||||
import com.android.sdk.qrcode.QRCodeView; |
|
||||||
import com.android.sdk.qrcode.Debug; |
|
||||||
import com.google.zxing.BinaryBitmap; |
import com.google.zxing.BinaryBitmap; |
||||||
import com.google.zxing.MultiFormatReader; |
import com.google.zxing.MultiFormatReader; |
||||||
import com.google.zxing.PlanarYUVLuminanceSource; |
import com.google.zxing.PlanarYUVLuminanceSource; |
Loading…
Reference in new issue