Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图的圆切图,Kotlin(4)

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图的圆切图,Kotlin(4)

这篇 Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(3)-CSDN博客 虽然实现了上图绘制手指在屏幕滑动的轨迹,且在下面的切图中用中心圆圈标记出当前手指在图中的位置,但没有在下面的切图中也绘制出与上图的手指滑动轨迹,下面实现这个功能:手指在原图中滑动,在切图中用圆圈标记手指的位置,同时在切图中复刻手指滑动的轨迹。

Kotlin 复制代码
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapShader
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.Shader.TileMode
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.PaintDrawable
import android.os.Bundle
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView


class MainActivity : AppCompatActivity() {
    private var iv: MyImageView? = null

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

        val r = findViewById<ImageView>(R.id.result)
        iv?.setTestImageView(r)
    }
}

class MyImageView : AppCompatImageView {
    private var mCurX = 0
    private var mCurY = 0

    private val mPath1 = Path()
    private val mPath2 = Path()
    private val mPathPaint1 = Paint()
    private val mPathPaint2 = Paint()
    private val mCirclePaint = Paint()

    private var mNewBmp: Bitmap? = null
    private var mSrcBmp: Bitmap? = null
    private var mIsDraw = false
    private val mRadius = 300f

    private var mDrawable: PaintDrawable? = null

    private var testIV: ImageView? = null

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
        mSrcBmp = (drawable as BitmapDrawable).bitmap

        mPathPaint1.style = Paint.Style.STROKE
        mPathPaint1.strokeWidth = 15f
        mPathPaint1.isAntiAlias = true
        mPathPaint1.color = Color.RED

        mPathPaint2.style = Paint.Style.STROKE
        mPathPaint2.strokeWidth = 20f
        mPathPaint2.isAntiAlias = true
        mPathPaint2.color = Color.YELLOW

        mCirclePaint.style = Paint.Style.STROKE
        mCirclePaint.strokeWidth = 25f
        mCirclePaint.isAntiAlias = true
        mCirclePaint.color = Color.BLUE
    }

    fun setTestImageView(iv: ImageView?) {
        testIV = iv
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        mCurX = event.x.toInt()
        mCurY = event.y.toInt()

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mPath1.moveTo(event.x, event.y)
                mPath2.moveTo(event.x, event.y)

                mIsDraw = true
            }

            MotionEvent.ACTION_MOVE -> {
                mPath1.lineTo(event.x, event.y)
                mPath2.lineTo(event.x, event.y)
            }

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

                //抬手后,清除手指轨迹。
                myClear()
            }
        }

        invalidate()

        return true
    }

    private fun myClear() {
        //清除历史轨迹。
        mPath1.reset()
        mPath2.reset()
    }

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

        if (mIsDraw) {
            myDraw()

            canvas.drawPath(mPath1, mPathPaint1)
        }
    }

    private fun myDraw() {
        val shader = BitmapShader(Bitmap.createScaledBitmap(mSrcBmp!!, this.width, this.height, true), TileMode.DECAL, TileMode.DECAL)
        mDrawable = PaintDrawable(Color.DKGRAY)
        mDrawable!!.setCornerRadius(mRadius / 2) //圆角矩形,如果不除2即是圆形框图。
        mDrawable!!.paint.shader = shader
        mDrawable!!.setBounds(0, 0, (mRadius * 2).toInt(), (mRadius * 2).toInt())

        mNewBmp = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
        val c = Canvas(mNewBmp!!)
        c.drawColor(Color.LTGRAY) //画满底色。

        val matrix = Matrix()
        matrix.setTranslate(-mCurX + mRadius, -mCurY + mRadius)
        mDrawable!!.paint.shader.setLocalMatrix(matrix)

        mDrawable!!.draw(c)


        val rectF = RectF()
        matrix.mapRect(rectF)

        val cx = mCurX + rectF.left
        val cy = mCurY + rectF.top
        c.drawCircle(cx, cy, 30f, mCirclePaint) //蓝色中心圆圈

        //下面小框图里面的Path
        val path = Path()
        mPath2.transform(matrix, path)
        c.drawPath(path, mPathPaint2) //绘制下面框图里面的Path

        testIV?.setImageBitmap(mNewBmp)
    }
}
XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.pkg.MyImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@drawable/ic_launcher_background"
        android:scaleType="fitCenter"
        android:src="@mipmap/mypic" />

    <ImageView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:background="@drawable/ic_launcher_background"
        android:src="@drawable/ic_launcher_foreground" />

</LinearLayout>

有两个遗留问题:

1、手指滑动出有效取景区域后,切图还在显示,这不是很合理。

2、最好只把黄色的轨迹线约束在圆角矩形的小切图框里面,不要在下面的切图小框外显示多余的黄色轨迹线。

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(3)-CSDN博客文章浏览阅读532次,点赞7次,收藏4次。基础上,增加一个功能,手指在上面的图中移动时,绘制红色移动轨迹(路线)同时,下面图中对应的小图中显示手指与屏幕的触点,这样可以"实时"指示当前手指在上面大图中移动的准确、精细位置。【代码】Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(2)【代码】Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(2)https://blog.csdn.net/zhangphil/article/details/135513118

相关推荐
allk5515 分钟前
Android 屏幕适配全维深度解析
android·性能优化·界面适配
Android系统攻城狮27 分钟前
Android ALSA驱动进阶之获取采样格式位宽snd_pcm_format_width:用法实例(九十八)
android·pcm·音频进阶·alsa驱动
莫比乌斯环1 小时前
【日常随笔】Android 跳离行为分析 - Instrumentation
android·架构·代码规范
aningxiaoxixi1 小时前
android 媒体之 MediaSession
android·媒体
GoldenPlayer1 小时前
Android文件权限报错
android
Jomurphys1 小时前
Compose 适配 - 全屏显示 EdgeToEdge
android
ii_best1 小时前
「安卓开发辅助工具按键精灵」xml全分辨率插件jsd插件脚本教程
android·xml·开发语言·编辑器·安卓
消失的旧时光-19431 小时前
从 Android 回调到 C 接口:函数指针 + void* self 的一次彻底理解
android·c语言·开发语言
dvlinker1 小时前
动态代理技术实战测评—高效解锁Zillow房价历史
android·java·数据库
峥嵘life1 小时前
Android16 EDLA 认证BTS测试Failed解决总结
android·java·linux·运维·学习