在?Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)?Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)-CSDN博客 基础上,改进,使得ImageView的scaleType为fitCenter高度match_parent后,顶部留出空白,也能准确的在手指触点显示放大镜:
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.RectF
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.widget.ImageView
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 = 4f
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 rectF = getBitmapBound(this)
val dx = (rectF.left - curX) * factor + curX
val dy = (rectF.top - curY) * factor + curY
//上下左右移动矩阵,使得放大后的矩阵处于圆圈的内容刚好是手指触点为中心的圆图。
matrix.postTranslate(dx, dy)
canvas.drawBitmap(
Bitmap.createScaledBitmap(originBmp, scaleW.toInt(), scaleH.toInt(), true),
matrix,
paint
)
}
private fun getBitmapBound(imageView: ImageView): RectF {
val bounds = RectF()
val drawable = imageView.drawable
if (drawable != null) {
imageView.imageMatrix.mapRect(bounds, RectF(drawable.bounds))
}
return bounds
}
}
<com.pkg.MyImage
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@mipmap/p2" />
ImageView由于高度在xml布局设置match_parent,撑满整个屏幕,但由于图像的Bitamp缩放为fitCenter没有充满整个ImageView。主要是计算ImageView里面Bitmap的RectF区域,然后顶部和坐标做一定偏移,对准手指触点位置。