enable media_selector, qucode

androidx
Zhanty 5 years ago
parent 92f605bca9
commit 881ece18b2
  1. 20
      lib_base/src/main/java/com/android/base/permission/AutoPermissionRequester.java
  2. 15
      lib_media_selector/README.md
  3. 22
      lib_media_selector/build.gradle
  4. 60
      lib_media_selector/src/github/java/uk/co/senab/photoview/Compat.java
  5. 100
      lib_media_selector/src/github/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java
  6. 285
      lib_media_selector/src/github/java/uk/co/senab/photoview/IPhotoView.java
  7. 284
      lib_media_selector/src/github/java/uk/co/senab/photoview/PhotoView.java
  8. 1373
      lib_media_selector/src/github/java/uk/co/senab/photoview/PhotoViewAttacher.java
  9. 149
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java
  10. 92
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/EclairGestureDetector.java
  11. 73
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/FroyoGestureDetector.java
  12. 30
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/GestureDetector.java
  13. 24
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/IRotateDetector.java
  14. 20
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/IRotateListener.java
  15. 27
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/OnGestureListener.java
  16. 113
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/RotateGestureDetector.java
  17. 42
      lib_media_selector/src/github/java/uk/co/senab/photoview/gestures/VersionedGestureDetector.java
  18. 35
      lib_media_selector/src/github/java/uk/co/senab/photoview/log/LogManager.java
  19. 116
      lib_media_selector/src/github/java/uk/co/senab/photoview/log/Logger.java
  20. 76
      lib_media_selector/src/github/java/uk/co/senab/photoview/log/LoggerDefault.java
  21. 61
      lib_media_selector/src/github/java/uk/co/senab/photoview/scrollerproxy/GingerScroller.java
  22. 33
      lib_media_selector/src/github/java/uk/co/senab/photoview/scrollerproxy/IcsScroller.java
  23. 58
      lib_media_selector/src/github/java/uk/co/senab/photoview/scrollerproxy/PreGingerScroller.java
  24. 48
      lib_media_selector/src/github/java/uk/co/senab/photoview/scrollerproxy/ScrollerProxy.java
  25. 5
      lib_media_selector/src/github/res/values/dimens.xml
  26. 3
      lib_media_selector/src/github/res/values/strings.xml
  27. 5
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/BoxingGlideLoader.java
  28. 14
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/BoxingUcrop.java
  29. 1
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/CropOptions.java
  30. 9
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/MediaSelector.java
  31. 3
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/SystemMediaSelector.java
  32. 5
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/Utils.java
  33. 2
      lib_qrcode/README.md
  34. 2
      lib_qrcode/build.gradle
  35. BIN
      lib_qrcode/libs/fotoapparat.aar
  36. 7
      lib_qrcode/src/main/java/com/android/sdk/qrcode/CameraUtils.java
  37. 2
      lib_qrcode/src/main/java/com/android/sdk/qrcode/QRCodeDecoder.java
  38. 2
      lib_qrcode/src/main/java/com/android/sdk/qrcode/QRCodeEncoder.java
  39. 74
      lib_qrcode/src/main/java/com/android/sdk/qrcode/QRCodeView.kt
  40. 4
      lib_qrcode/src/main/java/com/android/sdk/qrcode/ZXingView.java

@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import timber.log.Timber; import timber.log.Timber;
@ -128,11 +129,28 @@ public class AutoPermissionRequester {
FragmentManager supportFragmentManager = mActivity.getSupportFragmentManager(); FragmentManager supportFragmentManager = mActivity.getSupportFragmentManager();
AutoPermissionFragment fragment = (AutoPermissionFragment) supportFragmentManager.findFragmentByTag(AutoPermissionFragment.class.getName()); AutoPermissionFragment fragment = (AutoPermissionFragment) supportFragmentManager.findFragmentByTag(AutoPermissionFragment.class.getName());
Lifecycle.State currentState = mActivity.getLifecycle().getCurrentState();
if (currentState.isAtLeast(Lifecycle.State.RESUMED)) {
startRequestInternal(supportFragmentManager, fragment);
} else {
DefaultLifecycleObserver lifecycleObserver = new DefaultLifecycleObserver() {
@Override
public void onResume(@NonNull LifecycleOwner owner) {
mActivity.getLifecycle().removeObserver(this);
startRequestInternal(supportFragmentManager, fragment);
}
};
mActivity.getLifecycle().addObserver(lifecycleObserver);
}
}
private void startRequestInternal(FragmentManager supportFragmentManager, AutoPermissionFragment fragment) {
if (fragment == null) { if (fragment == null) {
fragment = AutoPermissionFragment.newInstance(); fragment = AutoPermissionFragment.newInstance();
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(fragment, AutoPermissionFragment.class.getName()) .add(fragment, AutoPermissionFragment.class.getName())
.commitNowAllowingStateLoss(); .commitAllowingStateLoss();
} }
fragment.setRequester(getCallback()); fragment.setRequester(getCallback());

@ -1,6 +1,6 @@
# 多媒体文件选择库 # 多媒体文件选择库
目前基于boxing修改 目前基于boxing修改
## 1 AndroidN 在 FileProvider 的 xm l配置中加入: ## 1 AndroidN 在 FileProvider 的 xm l配置中加入:
@ -9,16 +9,9 @@
<external-path name="external" path="DCIM/bili/boxing" /> <external-path name="external" path="DCIM/bili/boxing" />
``` ```
## 2 So库 ## 2 RotatePhotoView
``` [RotatePhotoView](https://github.com/ChenSiLiang/RotatePhotoView)
defaultConfig {
......
ndk {//只打包armeabi架构的so库
abiFilters 'armeabi'
}
}
```
## 3 其他备选参考 ## 3 其他备选参考
@ -29,4 +22,4 @@
-  [Album](https://github.com/yanzhenjie/Album) -  [Album](https://github.com/yanzhenjie/Album)
-  [uCrop](https://github.com/Yalantis/uCrop) -  [uCrop](https://github.com/Yalantis/uCrop)
-  [smartCropper](https://github.com/pqpo/SmartCropper) -  [smartCropper](https://github.com/pqpo/SmartCropper)
-  [simpleCropper](https:github.com/igreenwood/SimpleCropView) -  [simpleCropper](https://github.com/igreenwood/SimpleCropView)

@ -22,11 +22,19 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
sourceSets {
main {
java.srcDirs += "src/github/java"
res.srcDirs += "src/github/res"
}
}
} }
dependencies { dependencies {
//support //support
implementation androidLibraries.compat implementation androidLibraries.appcompat
implementation androidLibraries.material implementation androidLibraries.material
/*imageLoader*/ /*imageLoader*/
@ -38,17 +46,11 @@ dependencies {
implementation('com.bilibili:boxing-impl:1.0.4') { implementation('com.bilibili:boxing-impl:1.0.4') {
exclude group: 'com.android.support' exclude group: 'com.android.support'
exclude group: 'com.chensl.rotatephotoview'
} }
implementation('com.chensl.rotatephotoview:rotatephotoview:1.0.5') { implementation('com.github.yalantis:ucrop:2.2.4') {
exclude group: 'com.android.support', module: 'appcompat'
exclude group: 'com.android.support', module: 'support-v4'
exclude module: 'recyclerview-v7'
}
implementation('com.yalantis:ucrop:2.2.0') {
exclude group: 'com.android.support'
exclude group: 'com.squareup.okio'
exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.okhttp3'
} }
} }

@ -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>&nbsp;</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();
}
}

@ -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>

@ -18,8 +18,6 @@
package com.android.sdk.mediaselector; package com.android.sdk.mediaselector;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.ImageView; import android.widget.ImageView;
import com.bilibili.boxing.loader.IBoxingCallback; import com.bilibili.boxing.loader.IBoxingCallback;
@ -31,6 +29,9 @@ import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.target.Target;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/** /**
* use https://github.com/bumptech/glide as media loader. * use https://github.com/bumptech/glide as media loader.
* *

@ -21,15 +21,16 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import com.bilibili.boxing.loader.IBoxingCrop; import com.bilibili.boxing.loader.IBoxingCrop;
import com.bilibili.boxing.model.config.BoxingCropOption; import com.bilibili.boxing.model.config.BoxingCropOption;
import com.yalantis.ucrop.UCrop; import com.yalantis.ucrop.UCrop;
import com.ztiany.mediaselector.R; import com.ztiany.mediaselector.R;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
/** /**
* use Ucrop(https://github.com/Yalantis/uCrop) as the implement for {@link IBoxingCrop} * use Ucrop(https://github.com/Yalantis/uCrop) as the implement for {@link IBoxingCrop}
* *
@ -38,22 +39,24 @@ import com.ztiany.mediaselector.R;
final class BoxingUcrop implements IBoxingCrop { final class BoxingUcrop implements IBoxingCrop {
@Override @Override
public void onStartCrop(Context context, Fragment fragment, @NonNull BoxingCropOption cropConfig, public void onStartCrop(Context context, Fragment fragment, @NonNull BoxingCropOption cropConfig, @NonNull String path, int requestCode) {
@NonNull String path, int requestCode) {
Uri uri = new Uri.Builder() Uri uri = new Uri.Builder()
.scheme("file") .scheme("file")
.appendPath(path) .appendPath(path)
.build(); .build();
//参数 //参数
UCrop.Options crop = new UCrop.Options(); UCrop.Options crop = new UCrop.Options();
crop.setCompressionFormat(Bitmap.CompressFormat.JPEG); crop.setCompressionFormat(Bitmap.CompressFormat.JPEG);
crop.withMaxResultSize(cropConfig.getMaxWidth(), cropConfig.getMaxHeight()); crop.withMaxResultSize(cropConfig.getMaxWidth(), cropConfig.getMaxHeight());
crop.withAspectRatio(cropConfig.getAspectRatioX(), cropConfig.getAspectRatioY()); crop.withAspectRatio(cropConfig.getAspectRatioX(), cropConfig.getAspectRatioY());
//颜色 //颜色
int color = ContextCompat.getColor(context, R.color.boxing_colorPrimaryDark); int color = ContextCompat.getColor(context, R.color.boxing_colorPrimaryDark);
crop.setToolbarColor(color); crop.setToolbarColor(color);
crop.setStatusBarColor(color); crop.setStatusBarColor(color);
//开始裁减 //开始裁减
UCrop.of(uri, cropConfig.getDestination()) UCrop.of(uri, cropConfig.getDestination())
.withOptions(crop) .withOptions(crop)
@ -71,4 +74,5 @@ final class BoxingUcrop implements IBoxingCrop {
} }
return UCrop.getOutput(data); return UCrop.getOutput(data);
} }
} }

@ -78,5 +78,4 @@ public class CropOptions implements Serializable {
return this; return this;
} }
} }

@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import com.bilibili.boxing.Boxing; import com.bilibili.boxing.Boxing;
@ -22,6 +21,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import androidx.fragment.app.Fragment;
/** /**
* 基于 Boxing 的多媒体文件选择器 * 基于 Boxing 的多媒体文件选择器
* <pre> * <pre>
@ -110,12 +111,10 @@ public class MediaSelector {
private void start(BoxingConfig boxingConfig, int requestCode) { private void start(BoxingConfig boxingConfig, int requestCode) {
if (mFragment != null) { if (mFragment != null) {
Boxing boxing = Boxing.of(boxingConfig) Boxing boxing = Boxing.of(boxingConfig).withIntent(mFragment.getContext(), BoxingActivity.class);
.withIntent(mFragment.getContext(), BoxingActivity.class);
boxing.start(mFragment, requestCode); boxing.start(mFragment, requestCode);
} else if (mActivity != null) { } else if (mActivity != null) {
Boxing boxing = Boxing.of(boxingConfig) Boxing boxing = Boxing.of(boxingConfig).withIntent(mActivity, BoxingActivity.class);
.withIntent(mActivity, BoxingActivity.class);
boxing.start(mActivity, requestCode); boxing.start(mActivity, requestCode);
} }
} }

@ -4,12 +4,13 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import java.io.File; import java.io.File;
import androidx.fragment.app.Fragment;
/** /**
* 通过系统相册或者系统相机获取照片 * 通过系统相册或者系统相机获取照片
* <pre> * <pre>

@ -15,7 +15,6 @@ import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.text.TextUtils; import android.text.TextUtils;
import java.io.File; import java.io.File;
@ -23,6 +22,8 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import androidx.core.content.FileProvider;
/** /**
* See: * See:
* <pre> * <pre>
@ -35,7 +36,6 @@ import java.util.List;
*/ */
final class Utils { final class Utils {
private Utils() { private Utils() {
throw new UnsupportedOperationException("Utils"); throw new UnsupportedOperationException("Utils");
} }
@ -365,4 +365,5 @@ final class Utils {
// 最后通知图库更新 // 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath))); context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath)));
} }
} }

@ -1,3 +1,3 @@
## 二维码扫描库 # 二维码扫描库
修改自 [BGAQRCode-Android](https://github.com/bingoogolapple/BGAQRCode-Android) 修改自 [BGAQRCode-Android](https://github.com/bingoogolapple/BGAQRCode-Android)

@ -35,6 +35,6 @@ android {
dependencies { dependencies {
implementation 'com.google.zxing:core:3.3.3' implementation 'com.google.zxing:core:3.3.3'
api fileTree(dir: 'libs', include: ['*.jar', '*.aar']) api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
/*implementation uiLibraries.fotoapparat*/ implementation uiLibraries.fotoapparat
implementation kotlinLibraries.kotlinStdlib implementation kotlinLibraries.kotlinStdlib
} }

Binary file not shown.

@ -13,8 +13,7 @@ import java.util.List;
import io.fotoapparat.parameter.Resolution; import io.fotoapparat.parameter.Resolution;
@SuppressWarnings("unused") public class CameraUtils {
final class CameraUtils {
private static final double MAX_ASPECT_DISTORTION = 0.15;//最大比例偏差 private static final double MAX_ASPECT_DISTORTION = 0.15;//最大比例偏差
private static final int MIN_PREVIEW_PIXELS = 480 * 800;//小于此预览尺寸直接移除 private static final int MIN_PREVIEW_PIXELS = 480 * 800;//小于此预览尺寸直接移除
@ -26,7 +25,7 @@ final class CameraUtils {
} }
} }
static Resolution findBestPictureSize(Context context, Collection<Resolution> collection) { public static Resolution findBestPictureSize(Context context, Collection<Resolution> collection) {
if (collection.isEmpty()) { if (collection.isEmpty()) {
return null; return null;
} }
@ -36,7 +35,7 @@ final class CameraUtils {
return bestPictureResolution; return bestPictureResolution;
} }
static Resolution findBestPreviewSize(Context context, Collection<Resolution> collection) { public static Resolution findBestPreviewSize(Context context, Collection<Resolution> collection) {
if (collection.isEmpty()) { if (collection.isEmpty()) {
return null; return null;
} }

@ -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;

@ -18,14 +18,14 @@ abstract class QRCodeView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), ProcessDataTask.Delegate { ) : FrameLayout(context, attrs, defStyleAttr), ProcessDataTask.Delegate {
private lateinit var mCameraView: CameraView private lateinit var cameraView: CameraView
private lateinit var mFotoapparat: Fotoapparat private lateinit var fotoapparat: Fotoapparat
private lateinit var mScanBoxView: ScanBoxView private lateinit var scanBoxView: ScanBoxView
protected var mDelegate: Delegate? = null private var delegate: Delegate? = null
private var mProcessDataTask: ProcessDataTask? = null private var dataTask: ProcessDataTask? = null
protected var mSpotAble = false protected var spotAble = false
private val framingRect = Rect() private val framingRect = Rect()
private var framingRectInPreview: Rect? = null private var framingRectInPreview: Rect? = null
@ -35,16 +35,16 @@ abstract class QRCodeView @JvmOverloads constructor(
} }
private fun initView(context: Context, attrs: AttributeSet?) { private fun initView(context: Context, attrs: AttributeSet?) {
mCameraView = CameraView(getContext()) cameraView = CameraView(getContext())
mScanBoxView = ScanBoxView(getContext()) scanBoxView = ScanBoxView(getContext())
mScanBoxView.initCustomAttrs(context, attrs) scanBoxView.initCustomAttrs(context, attrs)
addView(mCameraView) addView(cameraView)
addView(mScanBoxView) addView(scanBoxView)
try { try {
mFotoapparat = createFotoapparat() fotoapparat = createFotoapparat()
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
mDelegate?.onScanQRCodeOpenCameraError(e) delegate?.onScanQRCodeOpenCameraError(e)
} }
} }
@ -65,27 +65,27 @@ abstract class QRCodeView @JvmOverloads constructor(
return Fotoapparat( return Fotoapparat(
context = this@QRCodeView.context, context = this@QRCodeView.context,
view = mCameraView, view = cameraView,
logger = logcat(), logger = logcat(),
lensPosition = back(), lensPosition = back(),
cameraConfiguration = configuration, cameraConfiguration = configuration,
cameraErrorCallback = { cameraErrorCallback = {
mDelegate?.onScanQRCodeOpenCameraError(it) delegate?.onScanQRCodeOpenCameraError(it)
} }
) )
} }
private fun processFrame(frame: Frame) { private fun processFrame(frame: Frame) {
val processDataTask = mProcessDataTask val processDataTask = dataTask
if (mSpotAble && (processDataTask == null || processDataTask.isCancelled)) { if (spotAble && (processDataTask == null || processDataTask.isCancelled)) {
mProcessDataTask = object : ProcessDataTask(frame.image, frame.size, frame.rotation, this) { dataTask = object : ProcessDataTask(frame.image, frame.size, frame.rotation, this) {
override fun onPostExecute(result: String?) { override fun onPostExecute(result: String?) {
if (mSpotAble) { if (spotAble) {
if (!result.isNullOrEmpty()) { if (!result.isNullOrEmpty()) {
try { try {
mDelegate?.onScanQRCodeSuccess(result) delegate?.onScanQRCodeSuccess(result)
stopSpot() stopSpot()
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -105,21 +105,21 @@ abstract class QRCodeView @JvmOverloads constructor(
* @param delegate 扫描二维码的代理 * @param delegate 扫描二维码的代理
*/ */
fun setDelegate(delegate: Delegate) { fun setDelegate(delegate: Delegate) {
mDelegate = delegate this.delegate = delegate
} }
/** /**
* 显示扫描框 * 显示扫描框
*/ */
fun showScanRect() { fun showScanRect() {
mScanBoxView.visibility = View.VISIBLE scanBoxView.visibility = View.VISIBLE
} }
/** /**
* 隐藏扫描框 * 隐藏扫描框
*/ */
fun hiddenScanRect() { fun hiddenScanRect() {
mScanBoxView.visibility = View.GONE scanBoxView.visibility = View.GONE
} }
/** /**
@ -127,7 +127,7 @@ abstract class QRCodeView @JvmOverloads constructor(
*/ */
fun startCamera() { fun startCamera() {
try { try {
mFotoapparat.start() fotoapparat.start()
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
throwable.printStackTrace() throwable.printStackTrace()
} }
@ -140,7 +140,7 @@ abstract class QRCodeView @JvmOverloads constructor(
fun stopCamera() { fun stopCamera() {
stopSpotAndHiddenRect() stopSpotAndHiddenRect()
try { try {
mFotoapparat.stop() fotoapparat.stop()
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
throwable.printStackTrace() throwable.printStackTrace()
} }
@ -151,7 +151,7 @@ abstract class QRCodeView @JvmOverloads constructor(
*/ */
fun startSpot() { fun startSpot() {
postDelayed({ postDelayed({
mSpotAble = true spotAble = true
startCamera() startCamera()
}, 100) }, 100)
} }
@ -161,7 +161,7 @@ abstract class QRCodeView @JvmOverloads constructor(
*/ */
fun stopSpot() { fun stopSpot() {
cancelProcessDataTask() cancelProcessDataTask()
mSpotAble = false spotAble = false
} }
/** /**
@ -186,14 +186,14 @@ abstract class QRCodeView @JvmOverloads constructor(
* @return * @return
*/ */
val isScanBarcodeStyle: Boolean val isScanBarcodeStyle: Boolean
get() = mScanBoxView.isBarcode get() = scanBoxView.isBarcode
/** /**
* 打开闪光灯 * 打开闪光灯
*/ */
fun openFlashlight() { fun openFlashlight() {
try { try {
mFotoapparat.updateConfiguration(UpdateConfiguration(flashMode = firstAvailable(torch(), off()))) fotoapparat.updateConfiguration(UpdateConfiguration(flashMode = firstAvailable(torch(), off())))
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@ -205,7 +205,7 @@ abstract class QRCodeView @JvmOverloads constructor(
*/ */
fun closeFlashlight() { fun closeFlashlight() {
try { try {
mFotoapparat.updateConfiguration(UpdateConfiguration(flashMode = firstAvailable(off()))) fotoapparat.updateConfiguration(UpdateConfiguration(flashMode = firstAvailable(off())))
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@ -216,29 +216,29 @@ abstract class QRCodeView @JvmOverloads constructor(
* 销毁二维码扫描控件 * 销毁二维码扫描控件
*/ */
fun onDestroy() { fun onDestroy() {
mDelegate = null delegate = null
} }
/** /**
* 取消数据处理任务 * 取消数据处理任务
*/ */
protected fun cancelProcessDataTask() { protected fun cancelProcessDataTask() {
mProcessDataTask?.cancelTask() dataTask?.cancelTask()
mProcessDataTask = null dataTask = null
} }
/** /**
* 切换成扫描条码样式 * 切换成扫描条码样式
*/ */
fun changeToScanBarcodeStyle() { fun changeToScanBarcodeStyle() {
mScanBoxView.isBarcode = true scanBoxView.isBarcode = true
} }
/** /**
* 切换成扫描二维码样式 * 切换成扫描二维码样式
*/ */
fun changeToScanQRCodeStyle() { fun changeToScanQRCodeStyle() {
mScanBoxView.isBarcode = false scanBoxView.isBarcode = false
} }
fun setDebug(debug: Boolean) { fun setDebug(debug: Boolean) {
@ -246,7 +246,7 @@ abstract class QRCodeView @JvmOverloads constructor(
} }
protected fun getFramingRectInPreview(previewWidth: Int, previewHeight: Int): Rect? { protected fun getFramingRectInPreview(previewWidth: Int, previewHeight: Int): Rect? {
if (!mScanBoxView.getScanBoxAreaRect(framingRect)) { if (!scanBoxView.getScanBoxAreaRect(framingRect)) {
return null return null
} }
if (framingRectInPreview == null) { if (framingRectInPreview == null) {
@ -274,7 +274,7 @@ abstract class QRCodeView @JvmOverloads constructor(
/** /**
* 处理打开相机出错 * 处理打开相机出错
*/ */
fun onScanQRCodeOpenCameraError(error: java.lang.Exception) fun onScanQRCodeOpenCameraError(error: Exception)
} }

@ -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…
Cancel
Save