支持单指滑动双指缩放的ImageView

支持单指滑动双指缩放的ImageView


import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

/**
 * 使用与正常imageview没有任何区别,而这个imageview支持的是双指缩放,把它放在任何布局中都可以,已经解决好了嵌套滑动等手势冲突的问题
 * 需要配合 MakeUpZoomImage 使用
 *
 * @see MakeUpZoomImage
 */
public class ZoomImageView extends android.support.v7.widget.AppCompatImageView {
    private static final String TAG = "ZoomImageView";
    private double lastD;
    private Point lastCenter;
    private int pCont;

    public ZoomImageView(Context context) {
        super(context);
        setClickable(true);
    }

    public ZoomImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setClickable(true);
    }

    public ZoomImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setClickable(true);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                pCont = 1;
                return true;
            case MotionEvent.ACTION_POINTER_DOWN:
                pCont++;
                if (pCont >= 2) {
                    setElevation(100);
                    bringToFront();
                    getParent().requestDisallowInterceptTouchEvent(true);
                    lastD = getDistance(event);
                    lastCenter = getCurrentPoint(event);
                }
                return true;
            case MotionEvent.ACTION_POINTER_UP:
                pCont--;
                return true;
            case MotionEvent.ACTION_MOVE:
                if (event.getPointerCount() >= 2) {
                    double moved = getDistance(event) - lastD;
                    double viewSize = Math.sqrt(getWidth() * getWidth() + getHeight() * getHeight());
                    double scale = (moved / viewSize);
                    Log.d(TAG, scale + "   " + lastD);
                    setVisibility(INVISIBLE);
                    Point point = getCurrentPoint(event);
                    float tx = point.x - lastCenter.x;
                    float ty = point.y - lastCenter.y;
                    MakeUpZoomImage.get().update(this, getDrawable(), scale + 1, tx, ty);
                    return true;
                }
                return true;
            case MotionEvent.ACTION_UP:
                MakeUpZoomImage.get().remove();
                setVisibility(VISIBLE);
                getParent().requestDisallowInterceptTouchEvent(false);
                pCont = 0;
                setScaleX(1);
                setScaleY(1);
                return true;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    private Point getCurrentPoint(MotionEvent event) {
        float x0 = event.getX(0);
        float y0 = event.getY(0);
        float x1 = event.getX(1);
        float y1 = event.getY(1);
        Point point = new Point(((int) (x1 + x0) / 2), ((int) (y1 + y0) / 2));
        return point;
    }

    private double getDistance(MotionEvent event) {
        float x0 = event.getX(0);
        float y0 = event.getY(0);
        float x1 = event.getX(1);
        float y1 = event.getY(1);

        return Math.sqrt((
                (y1 - y0) * (y1 - y0))
                + ((x1 - x0) * (x1 - x0))
        );
    }

}

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class MakeUpZoomImage {
    private Activity activity;
    private volatile static MakeUpZoomImage makeUpZoomImage;
    private ImageView imageView;

    private MakeUpZoomImage(Activity activity) {
        this.activity = activity;
        imageView = new ImageView(activity);
        activity.addContentView(imageView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));
        imageView.setVisibility(View.GONE);
    }

    public static MakeUpZoomImage attach(Activity activity) {
        if (makeUpZoomImage == null) {
            synchronized (MakeUpZoomImage.class) {
                if (makeUpZoomImage == null) {
                    makeUpZoomImage = new MakeUpZoomImage(activity);
                }
            }
        }
        return makeUpZoomImage;
    }

    public static MakeUpZoomImage get() {
        if (makeUpZoomImage == null) {
            synchronized (MakeUpZoomImage.class) {
                if (makeUpZoomImage == null) {
                    throw new IllegalStateException("Must be initialized");
                }
            }
        }
        return makeUpZoomImage;
    }

    public void release() {
        remove();
        makeUpZoomImage = null;
    }

    public void update(View view, Drawable drawable, double zoom, float tx, float ty) {
        if (view == null) {
            return;
        }
        int[] location = new int[2];
        view.getLocationInWindow(location);

        ViewGroup.LayoutParams lp = imageView.getLayoutParams();
        lp.width = view.getWidth();
        lp.height = view.getHeight();
        imageView.setLayoutParams(lp);
        imageView.setX(location[0] + tx);
        imageView.setY(location[1] - getNotificationBarHeight() + ty);

        imageView.setVisibility(View.VISIBLE);
        imageView.setImageDrawable(drawable);
        imageView.setScaleX((float) zoom);
        imageView.setScaleY((float) zoom);
    }

    private int getNotificationBarHeight() {
        Resources resources = activity.getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }

    public void remove() {
        imageView.setVisibility(View.GONE);
        imageView.setImageDrawable(null);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现 Android 中的图片单指滑动双指缩放功能,可以使用 GestureDetector 和 ScaleGestureDetector 两个类。 首先,创建一个自定义的 ImageView 组件,并在其中重写 onTouchEvent 方法。在该方法中,可以判断手势的类型,然后分别处理手势事件。 以下是示例代码: ```java public class MyImageView extends ImageView { private GestureDetector gestureDetector; private ScaleGestureDetector scaleGestureDetector; private float scaleFactor = 1.0f; private float lastX = -1; private float lastY = -1; public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); gestureDetector = new GestureDetector(context, new GestureListener()); scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getPointerCount() == 1) { // 处理单指滑动 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = event.getX(); lastY = event.getY(); break; case MotionEvent.ACTION_MOVE: float dx = event.getX() - lastX; float dy = event.getY() - lastY; lastX = event.getX(); lastY = event.getY(); scrollBy((int) -dx, (int) -dy); break; } return true; } else { // 处理双指缩放 gestureDetector.onTouchEvent(event); scaleGestureDetector.onTouchEvent(event); return true; } } private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { scrollBy((int) distanceX, (int) distanceY); return true; } } private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5.0f)); // 设置缩放范围 setScaleX(scaleFactor); setScaleY(scaleFactor); return true; } } } ``` 在该代码中,我们使用 GestureDetector 处理单指滑动事件,使用 ScaleGestureDetector 处理双指缩放事件。在单指滑动事件中,我们根据手指移动的距离来调用 scrollBy 方法来实现视图的移动。在双指缩放事件中,我们根据手指之间的距离来计算缩放比例,然后调用 setScaleX 和 setScaleY 方法来改变视图的缩放比例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

痕迹丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值