Посмотреть пейджер + ImageView +Pinch Zoom + Поворот
Я хочу реализовать Pinch Zoom для ImageView, с помощью View Pager, похожего на галерею Android по умолчанию. Я нашел несколько источников через GitHub, но масштабирование и скольжение работают только для первого изображения.
Что я пробовал:
1.) TouchImageView
2.) PhotoView
Все вышеперечисленные ссылки отлично работают для просмотра одного изображения. Но когда дело доходит до изображений в пейджере View, они имеют некоторые глюки и прекрасно работают только для первого изображения в пейджере View. Когда мы переходим к 3-му 4-му изображению в пейджере, функция перетаскивания не работает должным образом, если изображение увеличено.
Пожалуйста, если кто-нибудь знает какую-либо хорошую библиотеку для этого, предоставьте мне ссылку на них.
7 ответов
РЕДАКТИРОВАТЬ 2: Пример кода был передан в главную ветку TouchImageView. Вот ссылка на пример деятельности и ссылка на ExtendedViewPager.
РЕДАКТИРОВАТЬ: добавлен код, адаптирующий пример ссылки на TouchImageView. Примечание: вам понадобится последний код, который в данный момент находится в ветке dev. В будущем это будет включено в v1.2.0. Вы знаете, что имеете последний код, если TouchImageView переопределяет canScrollHorizontally.
Шаг 1: Расширьте ViewPager и переопределите canScroll для вызова canScrollHorizontallyFroyo.
public class ExtendedViewPager extends ViewPager {
public ExtendedViewPager(Context context) {
super(context);
}
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof TouchImageView) {
return ((TouchImageView) v).canScrollHorizontallyFroyo(-dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
}
Шаг 2. Измените TouchImageView, добавив canScrollHorizontallyFroyo:
public boolean canScrollHorizontallyFroyo(int direction) {
return canScrollHorizontally(direction);
}
Шаг 3: Ваша деятельность
public class TouchImageViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ExtendedViewPager mViewPager = (ExtendedViewPager) findViewById(R.id.view_pager);
setContentView(mViewPager);
mViewPager.setAdapter(new TouchImageAdapter());
}
static class TouchImageAdapter extends PagerAdapter {
private static int[] images = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
@Override
public int getCount() {
return images.length;
}
@Override
public View instantiateItem(ViewGroup container, int position) {
TouchImageView img = new TouchImageView(container.getContext());
img.setImageResource(images[position]);
container.addView(img, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
return img;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}
Шаг 4: main.xml
<com.example.touch.ExtendedViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
TouchImageView на самом деле мой проект. В настоящее время у меня есть исправление в ветке dev для интеграции с ViewPagers, которое будет передано мастеру в следующем выпуске. К сожалению, это исправление применимо только для API 14 и выше, так как сотовые и более ранние версии не вызывают canScrollHorizontally
, Если вам нужно поддерживать более старые API, вам нужно будет обойти это в вашем ViewPager. Вот пример.
Я нашел симпатичное решение с библиотекой ImageViewZoom. Чтобы прокрутить увеличенное изображение в ViewPager, я создал собственный ViewPager:
public class ExtendedViewPager extends ViewPager {
public ExtendedViewPager(Context context) {
super(context);
}
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
return ((ImageViewTouch) v).canScroll(dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
}
После нескольких часов тестирования вышеупомянутых решений я наконец-то нашел потрясающую библиотеку View View с масштабированием субсэмплинга, которая работает даже со стандартным ViewPager из пакета поддержки Android.
Мое решение с использованием библиотеки ImageViewZoom основано на этом пользовательском ViewPager:
public class ImageViewTouchViewPager extends ViewPager {
public ImageViewTouchViewPager(Context context) {
super(context);
}
public ImageViewTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
ImageViewTouch imageViewTouch = (ImageViewTouch)v;
if (imageViewTouch.getScale() == imageViewTouch.getMinScale()) {
return super.canScroll(v, checkV, dx, x, y);
}
return imageViewTouchCanScroll(imageViewTouch, dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
/**
* Determines whether the ImageViewTouch can be scrolled.
*
* @param direction - positive direction value means scroll from right to left,
* negative value means scroll from left to right
* @return true if there is some more place to scroll, false - otherwise.
*/
private boolean imageViewTouchCanScroll(ImageViewTouch v, int direction){
RectF bitmapRect = v.getBitmapRect();
Rect imageViewRect = new Rect();
getGlobalVisibleRect(imageViewRect);
if (null == bitmapRect) {
return false;
}
if (direction < 0) {
return Math.abs(bitmapRect.right - imageViewRect.right) > 1.0f;
}else {
return Math.abs(bitmapRect.left - imageViewRect.left) > 1.0f;
}
}
}
Для тех, кто изо всех сил пытается отключить окно просмотра, когда изображение зажато для увеличения, и включить, когда изображение находится в исходном состоянии. Я просто внес некоторые изменения, как ответил Майк.
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.viewpager.widget.ViewPager
class DCExtendedViewPager : ViewPager {
private val TAG = DCExtendedViewPager::class.java.simpleName
private var onImageState: OnImageState? = null
private var touchImageViewCustom: DCTouchImageViewLatest? = null
var isScroll: Boolean = true
interface OnImageState {
fun checkImageState(isImageInOriginalState: Boolean)
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
override fun canScroll(view: View, checkV: Boolean, dx: Int, x: Int, y: Int): Boolean {
return if (view is DCTouchImageViewLatest) {
// touchImageView=view
// canScrollHorizontally is not supported for Api < 14. To get around this issue,
// ViewPager is extended and canScrollHorizontallyFroyo, a wrapper around
// canScrollHorizontally supporting Api >= 8, is called.
Log.e("ExtendedViewPager", "canScroll zoomedRect" + view.zoomedRect)
view.canScrollHorizontallyFroyo(-dx)
} else {
super.canScroll(view, checkV, dx, x, y)
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
Log.e(TAG, "onTouchEventenable" + isScroll)
return if (isScroll) {
super.onTouchEvent(event)
} else false
}
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
Log.e(TAG, "onInterceptTouchEvent")
Log.e(TAG, "currenrLayoutView called")
val currenrLayoutView = getCurrentParentView()
getTouchImageViewInstance(currenrLayoutView!!)
return if (isScroll) {
super.onInterceptTouchEvent(event)
} else false
}
fun isViewPagerScrollValid(): Boolean {
Log.e(TAG, "getFocusedChild()" + focusedChild)
val currenrLayoutView = getCurrentParentView()
var zoomRect = getTouchImageViewInstance(currenrLayoutView!!)?.zoomedRect
var orgzoomRect = getTouchImageViewInstance(currenrLayoutView)?.originalRectF
Log.e(TAG, "onInterceptTouchEvent zoomRect" + zoomRect)
Log.e(TAG, "onInterceptTouchEvent orgzoomRect" + orgzoomRect)
Log.e(TAG, "onInterceptTouchEvent onImageState" + onImageState)
var scrollEnable = (zoomRect == orgzoomRect)
// postLater(getTouchImageViewInstance(currenrLayoutView!!)!!)
onImageState?.checkImageState(scrollEnable)
Log.e(TAG, "onInterceptTouchEvent" + scrollEnable)
return scrollEnable
}
fun setImageStateListner(onImageState: OnImageState) {
this.onImageState = onImageState
}
fun getTouchImageViewInstance(accessingView: View): DCTouchImageViewLatest? {
if (touchImageViewCustom == null) {
try {
for (index in 0 until (accessingView as ViewGroup).childCount) {
var nextChild = accessingView.getChildAt(index)
Log.e(TAG, "nextChild" + nextChild)
if (nextChild is ViewGroup) {
getTouchImageViewInstance(nextChild)
} else if (nextChild is View) {
if (nextChild is DCTouchImageViewLatest) {
touchImageViewCustom = nextChild
setListner()
break
}
}
}
} catch (ex: Exception) {
ex.printStackTrace()
}
}
Log.e(TAG, "getTouchImageViewInstance" + touchImageViewCustom)
return touchImageViewCustom
}
private fun setListner() {
touchImageViewCustom?.setOnDCTouchImageViewLatestListener(object : DCTouchImageViewLatest.OnDCTouchImageViewLatestListener {
override fun onMove() {
Log.e(TAG, "onMove Called")
isScroll = isViewPagerScrollValid()
}
})
}
//Call this method from onPageSelected of viewpager
fun viewPageChanged() {
Log.e(TAG, "viewPageChanged called")
touchImageViewCustom = null
}
fun getCurrentParentView(): View? {
try {
Log.e(TAG, "getCurrentView called")
val currentItem = currentItem
for (i in 0 until childCount) {
val child = getChildAt(i)
val layoutParams = child.layoutParams as ViewPager.LayoutParams
val f = layoutParams.javaClass.getDeclaredField("position") //NoSuchFieldException
f.isAccessible = true
val position = f.get(layoutParams) as Int //IllegalAccessException
Log.e(TAG, "currentItem" + currentItem)
if (!layoutParams.isDecor && currentItem == position) {
Log.e(TAG, "getCurrentView" + child)
return child
}
}
} catch (e: NoSuchFieldException) {
Log.e(TAG, e.toString())
} catch (e: IllegalArgumentException) {
Log.e(TAG, e.toString())
} catch (e: IllegalAccessException) {
Log.e(TAG, e.toString())
}
return null
}
}
В классе TouchImageView вызовите getOriginalRectF() из setImageBitmap, setImageDrawable и setImageURI.
public RectF getOriginalRectF(){
Log.e(TAG,"getOriginalRectF called viewWidth"+viewWidth);
Log.e(TAG,"getOriginalRectF called viewHeight"+viewHeight);
if(originalRectF==null && viewHeight>0 && viewWidth>0){
if (mScaleType == ScaleType.FIT_XY) {
throw new UnsupportedOperationException("getZoomedRect() not supported with FIT_XY");
}
PointF topLeft = transformCoordTouchToBitmap(0, 0, true);
PointF bottomRight = transformCoordTouchToBitmap(viewWidth, viewHeight, true);
float w = getDrawableWidth(getDrawable());
float h = getDrawableHeight(getDrawable());
Log.e(TAG,"getOriginalRectF height"+h);
Log.e(TAG,"getOriginalRectF width"+w);
Log.e("getOriginalRectF","getZoomedRect topLeft"+topLeft.x +"-"+topLeft.y);
Log.e("getOriginalRectF","getZoomedRect bottomRight"+bottomRight.x +"-"+bottomRight.y);
originalRectF=new RectF(topLeft.x / w, topLeft.y / h, bottomRight.x / w, bottomRight.y / h);
}
return originalRectF;
}
Я исправил предыдущее решение. Вы можете прокрутить страницу, когда ImageViewTouch находится в режиме масштабирования.
public class ImageViewTouchViewPager extends ViewPager {
public ImageViewTouchViewPager(Context context) {
super(context);
}
public ImageViewTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
ImageViewTouch imageViewTouch = (ImageViewTouch)v;
return imageViewTouchCanScroll(imageViewTouch, dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
/**
* Determines whether the ImageViewTouch can be scrolled.
*
* @param direction - positive direction value means scroll from right to left,
* negative value means scroll from left to right
* @return true if there is some more place to scroll, false - otherwise.
*/
private boolean imageViewTouchCanScroll(ImageViewTouch imageViewTouch, int direction){
int widthScreen = getWidthScreen();
RectF bitmapRect = imageViewTouch.getBitmapRect();
Rect imageViewRect = new Rect();
getGlobalVisibleRect(imageViewRect);
int widthBitmapViewTouch = (int)bitmapRect.width();
if (null == bitmapRect) {
return false;
}
if(widthBitmapViewTouch < widthScreen){
return false;
}
if (direction < 0) {
return Math.abs(bitmapRect.right - imageViewRect.right) > 1.0f;
}else {
return Math.abs(bitmapRect.left - imageViewRect.left) > 1.0f;
}
}
private int getWidthScreen(){
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size.x;
}
}
Ни одно из вышеперечисленных решений не сработало для меня. Это сработало для меня, когда я использовал следующий ImageView:
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
@SuppressLint("AppCompatCustomView")
public class TouchImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,View.OnTouchListener {
private final static int SINGLE_TOUCH = 1; //Single point
private final static int DOUBLE_TOUCH = 2; //Double finger
//Multi-finger touch mode, single finger, double finger
private int mode;
//Distance between two finger touch points
private float oldDist;
private float newDist;
/**
* Maximum zoom level
*/
private static final float MAX_SCALE = 5f;
/**
* Double-click the zoom level
*/
private float mDoubleClickScale = 2;
/**
* Scales when initialization, if the picture is wide or higher than the screen, this value will be less than 0
*/
private float initScale = 1.0f;
private boolean once = true;
private RectF rectF;
/**
* Double-click detection
*/
private GestureDetector mGestureDetector;
private int x = 0;
private int y = 0;
private Point mPoint = new Point();
private final Matrix matrix = new Matrix();
private Matrix oldMatrix = new Matrix();
private ValueAnimator animator;
public TouchImageView(Context context) {
this(context, null);
}
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
super.setScaleType(ScaleType.MATRIX);
setOnTouchListener(this);
/**
* Double click to implement the picture to zoom
*/
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
changeViewSize(e);
return true;
}
});
}
@Override
public boolean onTouch(View view, MotionEvent event) {
rectF = getMatrixRectF(); //Get image boundaries
if (mGestureDetector.onTouchEvent(event))
return true;
switch (event.getAction() & event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
//If the boundary of the picture is overstelled, then intercept the event, not letting ViewPager processing
if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
getParent().requestDisallowInterceptTouchEvent(true);
}
mode = SINGLE_TOUCH;
x = (int) event.getRawX();
y = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
if (mode >= DOUBLE_TOUCH) //Double finger zoom
{
getParent().requestDisallowInterceptTouchEvent(true);
newDist = calculateDist(event); //Calculate distance
Point point = getMiPoint(event); //Get the midpoint coordinates between the two-hand fingers
if (newDist > oldDist + 1) //Pixabay (add one to prevent jitter)
{
changeViewSize(oldDist, newDist, point); //Enlarge reduction according to distance
oldDist = newDist;
}
if (oldDist > newDist + 1) //Narrow
{
changeViewSize(oldDist, newDist, point);
oldDist = newDist;
}
}
if (mode == SINGLE_TOUCH) //Drag and drop
{
float dx = event.getRawX() - x;
float dy = event.getRawY() - y;
//If the boundary of the picture in the movement exceeds the screen, then intercept the event, do not let ViewPager processing
if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
getParent().requestDisallowInterceptTouchEvent(true);
}
//If you move the picture to the right, don't intercept the event, let the ViewPager process
if (rectF.left >= 0 && dx > 0)
getParent().requestDisallowInterceptTouchEvent(false);
//If you move to the left, don't intercept the event, let ViewPager processing
if (rectF.right <= getWidth() && dx < 0)
getParent().requestDisallowInterceptTouchEvent(false);
if (getDrawable() != null) {
//If the image width or height does not exceed the screen, then it is forbidden to slide around or down.
if (rectF.width() <= getWidth())
dx = 0;
if (rectF.height() < getHeight())
dy = 0;
//If the picture moves down to the end, don't let it continue to move
if (rectF.top >= 0 && dy > 0)
dy = 0;
//If the picture moves up to the end, don't let it continue to move
if (rectF.bottom <= getHeight() && dy < 0)
dy = 0;
//When the movement distance is greater than 1, it moves because Action_Move is relatively sensitive.
// The finger can only detect the jitter of the finger and let the picture move.
if (Math.abs(dx) > 1 || Math.abs(dy) > 1)
matrix.postTranslate(dx, dy);
setImageMatrix(matrix);
}
}
x = (int) event.getRawX();
y = (int) event.getRawY();
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode += 1;
oldDist = calculateDist(event);
Log.e("q", "" + "a");
Log.e(":::", "" + event.getPointerCount() + " " + event.getActionIndex() + " " + event.findPointerIndex(0));
break;
case MotionEvent.ACTION_POINTER_UP:
mode -= 1;
break;
case MotionEvent.ACTION_UP:
backToPosition();
mode = 0;
break;
//In Action_Move, the event is intercepted, sometimes Action_up can't trigger, so add Action_Cancel
case MotionEvent.ACTION_CANCEL:
backToPosition();
mode = 0;
break;
default:
break;
}
return true;
}
/**
* Calculate the distance between two finger touch points
*/
private float calculateDist(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
/**
* If it is separated from the screen boundary, then the image boundary is combined with the screen boundary.
* If the finger moves quickly, the picture will have a blank distance after the picture is stopped, and then the judgment can no longer move,
* However, it has appeared before the next judgment can continue to move.
* So you need to reset
*/
private void backToPosition() {
if (rectF.left >= 0) { //Image Left boundary and screen from the screen
matrix.postTranslate(-rectF.left, 0);
setImageMatrix(matrix);
}
if (rectF.right <= getWidth()) { //Image Right Boundary and Screen Distance
matrix.postTranslate(getWidth() - rectF.right, 0);
setImageMatrix(matrix);
}
if (rectF.top >= 0) { //Image on the image and the screen from the screen
matrix.postTranslate(0, -rectF.top);
setImageMatrix(matrix);
}
if (rectF.bottom <= getHeight()) { //Image of the image and the screen
matrix.postTranslate(0, getHeight() - rectF.bottom);
setImageMatrix(matrix);
}
}
/**
* Get the zoom in the zoom of double finger zoom
*
* @return
*/
private Point getMiPoint(MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
mPoint.set((int) x / 2, (int) y / 2);
return mPoint;
}
/**
* Double finger zoom picture
*/
private void changeViewSize(float oldDist, float newDist, Point mPoint) {
float scale = newDist / oldDist; //scaling ratio
matrix.postScale(scale, scale, mPoint.x, mPoint.y);
checkBorderAndCenterWhenScale();
setImageMatrix(matrix);
//Prevent reduction is less than the initial picture size, need to reset
reSetMatrix();
//If the zoom has been larger than the target multiple, stop, because it is possible to be exceeded, then directly zoom to the target size
if (getMatrixValueX() >= MAX_SCALE)
{
matrix.postScale(MAX_SCALE/getMatrixValueX(), MAX_SCALE/getMatrixValueX(), x, y);
checkBorderAndCenterWhenScale();
setImageMatrix(matrix);
return;
}
}
/**
* Double click to zoom pictures
*/
private void changeViewSize(MotionEvent e) {
//Get double-click coordinates
final float x = e.getX();
final float y = e.getY();
//If you are still zooming, you will return directly.
if (animator != null && animator.isRunning())
return;
//Judgment is a state in which it is amplified or reduced
if (!isZoomChanged()) {
animator = ValueAnimator.ofFloat(1.0f, 2.0f);
} else {
animator = ValueAnimator.ofFloat(1.0f, 0.0f);
}
animator.setTarget(this);
animator.setDuration(500);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Float value = (Float) animator.getAnimatedValue();
matrix.postScale(value, value, x, y);
checkBorderAndCenterWhenScale();
setImageMatrix(matrix);
/**
* Control reduction range
* If it is already less than the initial size, then restore to the initial size, then stop
*/
if (checkRestScale()) {
matrix.set(oldMatrix);
setImageMatrix(matrix);
return;
}
/**
* Control the range of amplification
* If the magnification of the target is already larger than the target, it is directly in the target magnification.
* Then stop
*/
if (getMatrixValueX() >= mDoubleClickScale)
{
matrix.postScale(mDoubleClickScale/getMatrixValueX(), mDoubleClickScale/getMatrixValueX(), x, y);
checkBorderAndCenterWhenScale();
setImageMatrix(matrix);
return;
}
}
});
}
/**
* Judging whether the zoom level is changed
*
* @return TRUE expressed the non-initial value, FALSE indicates the initial value.
*/
private boolean isZoomChanged() {
float[] values = new float[9];
getImageMatrix().getValues(values);
//Get the current X-axis scale level
float scale = values[Matrix.MSCALE_X];
//Get the X-axis scaling level of the template, both
oldMatrix.getValues(values);
return scale != values[Matrix.MSCALE_X];
}
/**
* Reset Matrix
*/
private void reSetMatrix() {
if (checkRestScale()) {
matrix.set(oldMatrix);
setImageMatrix(matrix);
return;
}
}
/**
* Setup double-click a large multiple
*/
private void setDoubleClickScale(RectF rectF)
{
if(rectF.height()<getHeight()-100)
{
mDoubleClickScale=getHeight()/rectF.height();
}
else
mDoubleClickScale=2f;
}
/**
* Judging whether it needs to be reset
*
* @return When the current zoom level is less than the template zoom level, reset
*/
private boolean checkRestScale() {
// TODO Auto-generated method stub
float[] values = new float[9];
getImageMatrix().getValues(values);
//Get the current X-axis scale level
float scale = values[Matrix.MSCALE_X];
//Get the X-axis scaling level of the template, both
oldMatrix.getValues(values);
return scale < values[Matrix.MSCALE_X];
}
private float getMatrixValueX()
{
// TODO Auto-generated method stub
float[] values = new float[9];
getImageMatrix().getValues(values);
//Get the current X-axis scale level
float scale = values[Matrix.MSCALE_X];
//Get the X-axis scaling level of the template, both
oldMatrix.getValues(values);
return scale / values[Matrix.MSCALE_X];
}
/**
* When zooming, perform image display scope control
*/
private void checkBorderAndCenterWhenScale()
{
RectF rect = getMatrixRectF();
float deltaX = 0;
float deltaY = 0;
int width = getWidth();
int height = getHeight();
// Control range if wide or higher than the screen
if (rect.width() >= width)
{
if (rect.left > 0)
{
deltaX = -rect.left;
}
if (rect.right < width)
{
deltaX = width - rect.right;
}
}
if (rect.height() >= height)
{
if (rect.top > 0)
{
deltaY = -rect.top;
}
if (rect.bottom < height)
{
deltaY = height - rect.bottom;
}
}
// If the width or higher is less than the screen, let it hit
if (rect.width() < width)
{
deltaX = width * 0.5f - rect.right + 0.5f * rect.width();
}
if (rect.height() < height)
{
deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();
}
Log.e("TAG", "deltaX = " + deltaX + " , deltaY = " + deltaY);
matrix.postTranslate(deltaX, deltaY);
setImageMatrix(matrix);
}
/**
* Get the range of images according to the Matrix of the current picture
*
* @return
*/
private RectF getMatrixRectF()
{
RectF rect = new RectF();
Drawable d = getDrawable();
if (null != d)
{
rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
matrix.mapRect(rect); //If this is not this, the output of the following Log will be the same as the previous sentence.
}
Log.e("aaaa",""+rect.bottom+" "+rect.left+" "+rect.right+" "+rect.top);
return rect;
}
@Override
public void onGlobalLayout() {
if (once)
{
Drawable d = getDrawable();
if (d == null)
return;
Log.e("TAG", d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());
int width = getWidth();
int height = getHeight();
// Get the width and high of the picture
int dw = d.getIntrinsicWidth();
int dh = d.getIntrinsicHeight();
float scale = 1.0f;
// If the image is wide or higher than the screen, zoom to the width or high of the screen.
if (dw > width && dh <= height)
{
scale = width * 1.0f / dw;
}
if (dh > height && dw <= width)
{
scale = height * 1.0f / dh;
}
// If the width and high are greater than the screen, it will make it adapt to the screen size according to the proportion.
if (dw > width && dh > height)
{
scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);
}
initScale = scale;
Log.e("TAG", "initScale = " + initScale);
matrix.postTranslate((width - dw) / 2, (height - dh) / 2);
matrix.postScale(scale, scale, getWidth() / 2,
getHeight() / 2);
// Image Move to the screen center
setImageMatrix(matrix);
oldMatrix.set(getImageMatrix());
once = false;
RectF rectF=getMatrixRectF();
setDoubleClickScale(rectF);
}
}
}
Кроме того, я использовал приведенный ниже ExtendedViewPager:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
public class ExtendedViewPager extends ViewPager {
public ExtendedViewPager(Context context) {
super(context);
}
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
try {
return super.onTouchEvent(ev);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
return false;
}
}