Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)

Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)

 

实现查看图片的放大镜,放大镜随着手指在屏幕上的移动,放大镜里面展示手指触点为中心、半径长度的圆形放大后的图片。

剪切出一块圆形Path,然后在圆形Path画放大后的图。因为是clipPath,只会显示Path区域内,区域外不显示。

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.Path
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


class MainActivity : AppCompatActivity() {
    private var image: MyImage? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        image = findViewById(R.id.image)
    }
}

class MyImage : AppCompatImageView {
    private val TAG = "fly"

    private var mIsDraw = false
    private var curX: Float = 0f
    private var curY: Float = 0f

    private var originBmp: Bitmap = (drawable as BitmapDrawable).bitmap

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                mIsDraw = true

                curX = event.x
                curY = event.y

                invalidate()
            }

            MotionEvent.ACTION_MOVE -> {
                curX = event.x
                curY = event.y

                invalidate()
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                mIsDraw = false

                invalidate()
            }
        }

        return true
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)

        if (canDraw()) {
            myDraw(canvas)
        }
    }

    private fun canDraw(): Boolean {
        return mIsDraw
    }

    /**
     * Matrix放大矩阵,然后通过clipPath剪切一块圆形区域作为放大镜区域,然后直接在clipPath的区域上绘制放大后的图。
     */
    private fun myDraw(canvas: Canvas) {
        Log.d(TAG, "ImageView w=${width} h=${height} Bitmap w=${originBmp.width} h=${originBmp.height}")

        val path = Path()
        val radius = 250f
        val factor = 2f

        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.color = Color.RED
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 10f

        path.addCircle(curX, curY, radius, Path.Direction.CW)
        canvas.drawPath(path, paint) //画红色的圆圈,圆心是手指在屏幕上的触点。

        canvas.clipPath(path) //剪切出来一片圆形区域。

        //特别注意,这里固定以手机屏幕的宽度为基准等比例放大Bitmap。
        val scaleW: Float = resources.displayMetrics.widthPixels.toFloat()
        val scaleH: Float = (originBmp.height.toFloat() / originBmp.width.toFloat()) * scaleW
        Log.d(TAG, "display w=${scaleW} h=${scaleH}")

        val matrix = Matrix()
        matrix.setScale(factor, factor)
        //canvas.concat(matrix)

        val dx = -curX * (factor - 1)
        val dy = -curY * (factor - 1)
        //上下左右移动矩阵,使得放大后的矩阵处于圆圈的内容刚好是手指触点为中心的圆图。
        matrix.postTranslate(dx, dy)

        canvas.drawBitmap(
            Bitmap.createScaledBitmap(originBmp, scaleW.toInt(), scaleH.toInt(), true),
            matrix,
            paint
        )
    }
}
    <com.pkg.MyImage
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@mipmap/p2" />

56bb0c6fcc9e44d49298a2d04b173020.png

需要注意的,因为在xml布局里面特别设置了ImageView的高度为wrap_content,手指在屏幕触点的位置是放大镜里面放大图片后准确圆心位置,但是,如果ImageView设置成match_parent,则因为ImageView里面的Bitmap被缩放(此处Bitmap其实小于ImageView,被拉伸了),拉伸后的Bitmap水平方向坐标与ImageView一直重合,但竖直方向,Bitmap坐标与ImageView不一致,会造成一种现象,手指触点放大镜放大后,水平方向是正确的,但竖直方向有偏移量。如果想要纠正竖直方向的偏移量,可以考虑调校Bitmap竖直方向顶部与ImageView顶部的坐标偏移。

Android Matrix画布Canvas缩放scale,Kotlin-CSDN博客文章浏览阅读168次,点赞3次,收藏3次。文章浏览阅读9.6k次。文章浏览阅读1.8k次。/*Java代码 将Drawable转化为Bitmap */ Bitmap drawableToBitmap(Drawable drawable) { int width = drawable.getIntrinsicWidth();Android Material Design :LinearLayoutCompat添加分割线divider_linearlayout 分割线-CSDN博客。https://blog.csdn.net/zhangphil/article/details/135114661

猜你喜欢

转载自blog.csdn.net/zhangphil/article/details/135172744