赞
踩
借鉴 Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)-CSDN博客 在此基础上实现手指在屏幕上点击后,动画放大图片,在放大过程中,移动手指触点位置到ImageView的中心。
- import android.content.Context
- import android.graphics.Bitmap
- import android.graphics.Canvas
- import android.graphics.Color
- import android.graphics.Matrix
- import android.graphics.Paint
- import android.graphics.RectF
- import android.graphics.drawable.BitmapDrawable
- import android.os.Bundle
- import android.util.AttributeSet
- import android.util.Log
- import android.view.MotionEvent
- import androidx.appcompat.app.AppCompatActivity
- import androidx.appcompat.widget.AppCompatImageView
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.delay
- import kotlinx.coroutines.launch
-
-
- class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
- }
-
- class MyImageView : AppCompatImageView {
- private var mCurX = 0f
- private var mCurY = 0f
- private var mCanDrawBitmap = false
-
- private var W = 0
- private var H = 0
-
- private val SCALE_FACTOR: Float = 5.5f
- private var mOriginBmp: Bitmap? = null
-
- private var mCirclePaint = Paint()
-
- private var mDeltaScaleFactor: Float = 0f
- private var mAnimScaleBmp: Bitmap? = null
-
- private var mCanDrawTouchPoint = false
- private var mTouchPointX = 0f
- private var mTouchPointY = 0f
-
- constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
- mCirclePaint.style = Paint.Style.STROKE
- mCirclePaint.strokeWidth = 10f
- mCirclePaint.isAntiAlias = true
- mCirclePaint.color = Color.RED
-
- mOriginBmp = (this.drawable as BitmapDrawable).bitmap
- }
-
- override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
- super.onSizeChanged(w, h, oldw, oldh)
-
- W = w
- H = h
- Log.d("fly", "W=$W H=$H")
- }
-
- override fun onTouchEvent(event: MotionEvent?): Boolean {
- if (event == null) {
- return false
- }
-
- mCurX = event.x
- mCurY = event.y
-
- when (event.actionMasked) {
- MotionEvent.ACTION_DOWN -> {
- //启动动画。
- startScaleAnim()
- }
- }
-
- return false
- }
-
- /**
- * Bitmap.createScaledBitmap耗时加剧卡顿。
- * 优化方案,基于原图setRectToRect缩放到给定宽w高h的放大图。
- */
- private fun getScaleBmp(w: Int, h: Int): Bitmap {
- val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
- val c = Canvas(bmp)
- c.drawColor(Color.BLUE)
-
- val src = RectF(0f, 0f, mOriginBmp!!.width.toFloat(), mOriginBmp!!.height.toFloat())
- val dst = RectF(0f, 0f, w.toFloat(), h.toFloat())
- val mx = Matrix()
- mx.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER)
- c.drawBitmap(mOriginBmp!!, mx, null)
-
- return bmp
- }
-
- private fun startScaleAnim() {
- val step = 50f //经过step后,完成缩放动画。
- val delta = (SCALE_FACTOR - 1) / step
-
- CoroutineScope(Dispatchers.IO).launch {
- //绘制在原图上手的触点。
- mTouchPointX = mCurX
- mTouchPointY = mCurY
- mCanDrawTouchPoint = true
- myPostInvalidate()
- delay(500) //延时,观察手指触点。
- mCanDrawTouchPoint = false
-
-
- mCanDrawBitmap = true
- for (i in 0 until step.toInt()) {
- mDeltaScaleFactor = 1f + delta * i
-
- /*
- mAnimScaleBmp = Bitmap.createScaledBitmap(
- mOriginBmp!!,
- (W * mDeltaScaleFactor + 1).toInt(), //注意精度损失,造成坐标偏移。
- (H * mDeltaScaleFactor + 1).toInt(),//注意精度损失,造成坐标偏移。
- true
- )
- */
- mAnimScaleBmp = getScaleBmp((W * mDeltaScaleFactor + 0.5).toInt(), (H * mDeltaScaleFactor + 0.5).toInt())
-
- //触发重绘。
- myPostInvalidate()
- }
-
-
- //for循环完成后,绘制最终图片动画放大完成后的中心圆点。
- mTouchPointX = W / 2f
- mTouchPointY = H / 2f
- mCanDrawTouchPoint = true
- myPostInvalidate()
- }
- }
-
- private fun myPostInvalidate() {
- this.postInvalidate()
- }
-
- private fun drawTouchPoint(c: Canvas) {
- c.drawCircle(mTouchPointX, mTouchPointY, 50f, mCirclePaint)
- }
-
- override fun onDraw(canvas: Canvas) {
- super.onDraw(canvas)
-
- if (mCanDrawBitmap) {
- val mx = Matrix()
- mx.setScale(mDeltaScaleFactor, mDeltaScaleFactor)
- mx.setTranslate(W / 2f - mCurX * mDeltaScaleFactor, H / 2f - mCurY * mDeltaScaleFactor)
- canvas.drawBitmap(mAnimScaleBmp!!, mx, null)
- }
-
- if (mCanDrawTouchPoint) {
- drawTouchPoint(canvas)
- }
- }
- }
Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)-CSDN博客文章浏览阅读613次,点赞4次,收藏5次。需要注意的,因为在xml布局里面特别设置了ImageView的高度为wrap_content,手指在屏幕触点的位置是放大镜里面放大图片后准确圆心位置,但是,如果ImageView设置成match_parent,则因为ImageView里面的Bitmap被缩放(此处Bitmap其实小于ImageView,被拉伸了),拉伸后的Bitmap水平方向坐标与ImageView一直重合,但竖直方向,Bitmap坐标与ImageView不一致,会造成一种现象,手指触点放大镜放大后,水平方向是正确的,但竖直方向有偏移量。https://blog.csdn.net/zhangphil/article/details/135701608Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客文章浏览阅读229次,点赞3次,收藏5次。【代码】Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin。https://blog.csdn.net/zhangphil/article/details/135960921
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。