📜  在Android中实现放大或缩小(1)

📅  最后修改于: 2023-12-03 15:07:51.878000             🧑  作者: Mango

在Android中实现放大或缩小

在Android开发中,有时需要让用户对界面进行放大或缩小操作。下面我们将介绍如何在Android中实现这个功能。

方案一:使用ScaleGestureDetector类

ScaleGestureDetector类是Android提供的一个手势识别工具,它可以识别用户的缩放手势,并提供缩放比例。

实现步骤
  1. 在布局文件中添加需要缩放的控件,代码片段如下:

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/image" />
    
  2. 在Activity中获取该控件,并声明ScaleGestureDetector类的对象和相关变量:

    private lateinit var mScaleGestureDetector: ScaleGestureDetector
    private var mScaleFactor = 1.0f
    private var mMinScaleFactor = 0.1f
    private var mMaxScaleFactor = 10.0f
    
    private val mOnScaleGestureListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            mScaleFactor *= detector.scaleFactor
            // 限制缩放范围
            mScaleFactor = Math.max(mMinScaleFactor, Math.min(mScaleFactor, mMaxScaleFactor))
    
            imageView.scaleX = mScaleFactor
            imageView.scaleY = mScaleFactor
    
            return true
        }
    }
    
  3. onCreate方法中为ScaleGestureDetector类对象赋值:

    mScaleGestureDetector = ScaleGestureDetector(this, mOnScaleGestureListener)
    
  4. onTouchEvent方法中调用ScaleGestureDetector类的onTouchEvent方法,以响应缩放手势:

    override fun onTouchEvent(event: MotionEvent): Boolean {
        mScaleGestureDetector.onTouchEvent(event)
        return true
    }
    
代码片段
private lateinit var mScaleGestureDetector: ScaleGestureDetector
private var mScaleFactor = 1.0f
private var mMinScaleFactor = 0.1f
private var mMaxScaleFactor = 10.0f

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val imageView = findViewById<ImageView>(R.id.imageView)

    mScaleGestureDetector = ScaleGestureDetector(this, mOnScaleGestureListener)
}

private val mOnScaleGestureListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
    override fun onScale(detector: ScaleGestureDetector): Boolean {
        mScaleFactor *= detector.scaleFactor
        mScaleFactor = Math.max(mMinScaleFactor, Math.min(mScaleFactor, mMaxScaleFactor))

        imageView.scaleX = mScaleFactor
        imageView.scaleY = mScaleFactor

        return true
    }
}

override fun onTouchEvent(event: MotionEvent): Boolean {
    mScaleGestureDetector.onTouchEvent(event)
    return true
}
方案二:使用Matrix类

另一种实现放大和缩小效果的方法是使用Matrix类,该类允许你在运行时对控件的样式和内容进行转换。

实现步骤
  1. 在布局文件中添加需要缩放的控件,代码片段如下:

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/image" />
    
  2. 在Activity中获取该控件,并声明Matrix类的对象:

    private lateinit var mImageView: ImageView
    private val mMatrix = Matrix()
    
  3. onCreate方法中为ImageView类对象赋值:

    mImageView = findViewById(R.id.imageView)
    
  4. onTouchEvent方法中对手势进行处理,代码片段如下:

    val pointerCount = event.pointerCount
    val action = event.actionMasked
    when (action) {
        MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
            if (pointerCount == 2) {
                // 设置缩放基准点
                mMatrix.setTranslate(event.getX(0), event.getY(0))
            }
        }
        MotionEvent.ACTION_MOVE -> {
            if (pointerCount == 2) {
                // 修改缩放比例
                val distance = distance(event.getX(0), event.getY(0), event.getX(1), event.getY(1))
                val scaleFactor = distance / mBaseDistance
                mMatrix.setScale(mBaseScale * scaleFactor, mBaseScale * scaleFactor)
            }
        }
        MotionEvent.ACTION_POINTER_UP -> {
            if (pointerCount == 2) {
                // 保存当前缩放比例
                mBaseScale = mMatrix.currentScale
            }
        }
    }
    // 更新ImageView的Matrix
    mImageView.imageMatrix = mMatrix
    
  5. 最后,还需定义和实现计算两个手指之间距离的方法:

    private fun distance(x1: Float, y1: Float, x2: Float, y2: Float): Float {
        val x = x1 - x2
        val y = y1 - y2
        return Math.sqrt(x * x + y * y.toDouble()).toFloat()
    }
    
代码片段
private lateinit var mImageView: ImageView
private val mMatrix = Matrix()
private var mBaseDistance = 0f
private var mBaseScale = 1f

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    mImageView = findViewById(R.id.imageView)
}

override fun onTouchEvent(event: MotionEvent): Boolean {
    val pointerCount = event.pointerCount
    val action = event.actionMasked
    when (action) {
        MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
            if (pointerCount == 2) {
                // 设置缩放基准点
                mMatrix.setTranslate(event.getX(0), event.getY(0))
            }
        }
        MotionEvent.ACTION_MOVE -> {
            if (pointerCount == 2) {
                // 修改缩放比例
                val distance = distance(event.getX(0), event.getY(0), event.getX(1), event.getY(1))
                val scaleFactor = distance / mBaseDistance
                mMatrix.setScale(mBaseScale * scaleFactor, mBaseScale * scaleFactor)
            }
        }
        MotionEvent.ACTION_POINTER_UP -> {
            if (pointerCount == 2) {
                // 保存当前缩放比例
                mBaseScale = mMatrix.currentScale
            }
        }
    }
    // 更新ImageView的Matrix
    mImageView.imageMatrix = mMatrix

    return true
}

private fun distance(x1: Float, y1: Float, x2: Float, y2: Float): Float {
    val x = x1 - x2
    val y = y1 - y2
    return Math.sqrt(x * x + y * y.toDouble()).toFloat()
}

以上就是两种实现放大和缩小效果的方法。你可以根据自己的需求选择其中一种方法来实现。