Android从零开始实现可以双指缩放,自由移动,双击放大的自定义ImageView

本文从零开始教你如何在Android中创建一个自定义ImageView,支持双指缩放、自由移动和双击放大功能。通过继承ImageView,实现等比缩放和居中显示,接着实现双击缩放、双指缩放和单指/双指移动图片的逻辑。文章附带完整代码,适合初级开发者学习。
摘要由CSDN通过智能技术生成

Android从零开始实现可以双指缩放,自由移动,双击放大的自定义ImageView

之前一直都是用别人的轮子,总感觉心里不踏实,所以自己也尝试这造一些别人造过的轮子,提升自己,也可以在平时开发中工作中更熟练的使用。
这一次从零开始,撸一个可单指移动,双击放大,双指缩放,双指移动的ImageView

这篇博文较长,如果向直接看完整代码,请直接拉到最后。

我们先来看看效果吧

第一步:继承ImageView,并让图片能等比缩放后居中显示


	public class ZoomImageView extends ImageView {
   
	
	
	    private Matrix matrix;
	
	    public ZoomImageView(Context context) {
   
	        super(context);
	        init();
	    }
	
	    public ZoomImageView(Context context, @Nullable AttributeSet attrs) {
   
	        super(context, attrs);
	        init();
	    }
	
	    public ZoomImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   
	        super(context, attrs, defStyleAttr);
	        init();
	    }
	
	    private void init(){
   
	        setScaleType(ScaleType.MATRIX);
	        matrix = new Matrix();
	    }
	}

布局时这样的

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.zoomimagetest.view.ZoomImageView
        android:id="@+id/my_image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/test5"/>

</androidx.constraintlayout.widget.ConstraintLayout>

运行后是这样的

图片没有显示全,那么接下来就让图片默认等比缩放然后居中显示

如果要实现等比缩放,需要知道ImageView 的宽高,以及图片的原始宽高,ImageView 的宽高这些信息可以再onMeasure方法中获取,而图片的宽高可以通过Drawable这个类拿到,下面代码中,获取图片的宽高时还有一个坑,这个后面再说。

	//imageView的大小
    private PointF viewSize;
    //图片的大小
    private PointF imageSize;

	@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        viewSize = new PointF(width,height);
        
        Drawable drawable = getDrawable();
        imageSize = new PointF(drawable.getMinimumWidth(),drawable.getMinimumHeight());
    }

然后我们ImageView的宽与图片的宽的比例,以及ImageView的高与图片的高的比例,对比宽和高的缩放比例,取较小的那个做为图片的缩放比例。

这里解释下为什么要用较小的那个做为图片的缩放比例,因为我们需要图片等比缩放,并且显示全,这里在同一部手机上,相同的这个自定义ZoomImageView中,可以认为viewSize的x,y是固定的,也就是在下面的式子中,分子是固定的,所以,如果整个值就越小,说明分母就越大,也就说明图片的这条边与这个view的这条边的差距越大,所以按照相差较大的这条边的缩放比例来缩放,肯定能保证在view中显示全。

	float scalex = viewSize.x/imageSize.x;
	float scaley = viewSize.y/imageSize.y;
	float scale = scalex<scaley?scalex:scaley;

得到我们的缩放比例后就可以对图片进行缩放了

	//缩放后图片的大小
    private PointF scaleSize = new PointF();
    public void scaleImage(PointF scaleXY){
   
        matrix.setScale(scaleXY.x,scaleXY.y);
        //这里将缩放后的图片大小保存一下
        scaleSize.set(scaleXY.x * imageSize.x,scaleXY.y * imageSize.y);
        setImageMatrix(matrix);
    }

到这一步的完整代码如下

@SuppressLint("AppCompatCustomView")
public class ZoomImageView extends ImageView {
   


    private Matrix matrix;
    //imageView的大小
    private PointF viewSize;
    //图片的大小
    private PointF imageSize;
    //缩放后图片的大小
    private PointF scaleSize = new PointF();
    //最初的宽高的缩放比例
    private PointF originScale = new PointF();


    public ZoomImageView(Context context) {
   
        super(context);
        init();
    }

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

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

    private void init(){
   
        setScaleType(ScaleType.MATRIX);
        matrix = new Matrix();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        viewSize = new PointF(width,height);

        Drawable drawable = getDrawable();
        imageSize = new PointF(drawable.getMinimumWidth(),drawable.getMinimumHeight());

        showCenter();
    }

    /**
     * 设置图片居中等比显示
     */
    private void showCenter(){
   
        float scalex = viewSize.x/imageSize.x;
        float scaley = viewSize.y/imageSize.y;

        float scale = scalex<scaley?scalex:scaley;
        scaleImage(new PointF(scale,scale));
    }


    /**
     * 将图片按照比例缩放,这里宽高缩放比例相等,所以PoinF 里面的x,y是一样的
     * @param scaleXY
     */
    public void scaleImage(PointF scaleXY){
   
        matrix.setScale(scaleXY.x,scaleXY.y);
        scaleSize.set(scaleXY.x * imageSize.x,scaleXY.y * imageSize.y);
        setImageMatrix(matrix);
    }

运行效果如下

到这里,图片是显示全了,但是并没有居中显示,那么接下来就来处理图片居中显示的问题。

	/**
     * 对图片进行x和y轴方向的平移
     * @param pointF
     */
    public void translationImage(PointF pointF){
   
        matrix.postTranslate(pointF.x,pointF.y);
        setImageMatrix(matrix);
    }

上面是对图片进行平移的方法

接下来需要计算,如果要图片在ImageView中居中显示,需要的平移量

	if (scalex<scaley){
   
         translationImage(new PointF(0,viewSize.y/2 - scaleSize.y/2));
     }else {
   
         translationImage(new PointF(viewSize.x/2 - scaleSize.x/2,0));
     }

前面讲过,两个方向的缩放值越小,说明那个方向的view的值与图片的值差距就越大,按照这个较小缩放值,缩放后,这个方向就正好充满view,那么此方向就不需要平移,平移另外一个方向即可。这里如果没有理解的,可以自己在纸上画个图。

那么到这里,第一步就等比缩放,居中显示就完成了。此时的全部代码如下

@SuppressLint("AppCompatCustomView")
public class ZoomImageView extends ImageView {
   


    private Matrix matrix;
    //imageView的大小
    private PointF viewSize;
    //图片的大小
    private PointF imageSize;
    //缩放后图片的大小
    private PointF scaleSize = new PointF();
    //最初的宽高的缩放比例
    private PointF originScale = new PointF();
    //imageview中bitmap的xy实时坐标
    private PointF bitmapOriginPoint = new PointF();


    public ZoomImageView(Context context) {
   
        super(context);
        init();
    }

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

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

    private 
  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 在Android平台上,可以使用一些常用的手势操作来实现图片的平移、双指缩放双击放大缩小。 首先,为了实现平移功能,可以使用触摸事件的ACTION_MOVE来处理手指在屏幕上滑动的操作。通过计算滑动距离,可以改变图片的位置从而实现平移效果。 其次,双指缩放可以使用触摸事件的ACTION_POINTER_DOWN和ACTION_POINTER_UP来追踪并处理触摸屏幕上第二个手指按下和松开的操作。在处理时,可以通过计算两个手指触摸点之间的距离来改变图片的缩放比例,从而实现双指缩放效果。 最后,双击放大缩小可以通过设置一个双击的监听器来实现。在双击监听器的回调方法中,可以根据当前的图片缩放状态来判断是进行放大操作还是缩小操作。并根据需要更改图片的缩放比例,实现双击放大缩小功能。 在实现上述功能时,可以使用Android提供的一些核心类来辅助开发,如View、MotionEvent、GestureDetector等。同时,还可以结合自定义View和动画效果来提升用户体验,使图片的平移、缩放双击动作更加流畅和自然。 总之,通过合理运用触摸事件、手势识别、双击监听器等技术,可以在Android实现图片的平移、双指缩放双击放大缩小功能,从而提升用户与应用程序的交互体验。 ### 回答2: 在Android开发中,可以通过使用ImageView控件来实现对图片的平移、双指缩放双击放大缩小操作。 1. 平移:可以通过使用Matrix类对ImageView进行变换来实现图片的平移。首先,我们需要为ImageView设置一个OnTouchListener来监听用户的手势操作。在手势操作的回调方法中,可以通过获取手指按下和移动的位置差来计算出需要平移的距离,然后通过设置Matrix的平移矩阵来实现图片的平移效果。 2. 双指缩放:可以通过GestureDetector类来监听双指缩放手势。在手势操作的回调方法中,可以获取到两个手指的起始位置和当前位置,通过计算两个手指之间的距离差来判断缩放的比例。然后,再通过设置Matrix的缩放矩阵来实现图片的缩放效果。需要注意的是,在进行缩放操作时,还需要考虑到手指中心点的位置变化。 3. 双击放大缩小:也可以通过GestureDetector类来监听双击手势。在手势操作的回调方法中,可以判断是否发生了双击事件,并获取到双击的位置。当双击事件发生时,可以通过判断当前图片的缩放比例来决定是放大还是缩小。通过设置Matrix的缩放矩阵和平移矩阵来实现图片的放大缩小效果。 需要注意的是,为了实现图片的平移、双指缩放双击放大缩小操作,我们需要对ImageView进行一系列的监听和处理操作。同时,为了方便管理和控制这些操作,可以将相关的代码封装成一个自定义的图片控件,并在该控件中进行处理。 ### 回答3: Android 提供了多种方法来实现图片的平移、双指缩放双击放大缩小功能。 首先,要实现图片的平移,我们可以使用 GestureDetector 类。可以通过重写 onScroll() 方法来检测用户的滑动手势,然后将图片的位置进行相应的调整,从而实现平移效果。 其次,要实现双指缩放功能,我们可以借助 ScaleGestureDetector 类。通过重写 onScale() 方法,我们可以获取用户的缩放手势,并根据手势的缩放比例调整图片的尺寸,从而实现双指缩放的效果。 最后,要实现双击放大缩小功能,我们可以使用 GestureDetector 类。可以通过重写 onDoubleTap() 方法来检测用户的双击手势,然后根据当前图片的尺寸和双击事件的位置,来判断是进行放大还是缩小操作,最后将图片的尺寸进行相应的调整,实现双击放大缩小的效果。 需要注意的是,以上的功能实现是基于 Android 的原生 API,还有其他第三方库也提供了更便捷的方法来实现这些功能,例如 PhotoView 库,它提供了更多灵活的选项和交互效果,可以更加方便地实现图片的平移、缩放双击操作。 综上所述,Android 针对图片的平移、双指缩放双击放大缩小,可以通过重写相应的手势监听方法或使用第三方库来实现
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值