Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin(二)

Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin(二)

Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin-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 = 0f
    private var mCurY = 0f

    private val mPath1 = Path()
    private val mPath2 = Path()

    private val mPathPaint1 = Paint()
    private val mPathPaint2 = Paint()
    private val mPathPaint3 = Paint()
    private val mCirclePaint = Paint()

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

    private var mDrawable: PaintDrawable? = null

    private var testIV: ImageView? = null

    //放大系数。
    private val mScaleFactor = 2.6f

    private var mBitmapShader: BitmapShader? = null

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
        mSrcBmp = (drawable as BitmapDrawable).bitmap //mSrcBmp是原始图大小,没有缩放和拉伸的。

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

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

        mPathPaint3.style = Paint.Style.STROKE
        mPathPaint3.strokeWidth = 3f
        mPathPaint3.isAntiAlias = true
        mPathPaint3.color = Color.GREEN

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

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

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

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mPath1.moveTo(mCurX, mCurY)
                mPath2.moveTo(mCurX * mScaleFactor, mCurY * mScaleFactor)

                mIsDraw = true
            }

            MotionEvent.ACTION_MOVE -> {
                mPath1.lineTo(mCurX, mCurY)
                mPath2.lineTo(mCurX * mScaleFactor, mCurY * mScaleFactor)
            }

            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() {
        if (mBitmapShader == null) {
            //创建一次,避免重复创建,提高速度。
            mBitmapShader = BitmapShader(
                Bitmap.createScaledBitmap(
                    mSrcBmp!!,
                    (this.width * mScaleFactor).toInt(), //注意这里的如果精度损失,会造成坐标偏移
                    (this.height * mScaleFactor).toInt(),//注意这里的如果精度损失,会造成坐标偏移
                    true
                ),
                TileMode.DECAL,
                TileMode.DECAL
            )
        }

        if (mDrawable == null) {
            //创建一次,避免重复创建,提高速度。
            mDrawable = PaintDrawable(Color.BLACK)
            mDrawable!!.setCornerRadius(mRadius / 2) //圆角矩形,如果不除2即是圆形框图。
            mDrawable!!.paint.shader = mBitmapShader
            mDrawable!!.setBounds(0, 0, (mRadius * 2).toInt(), (mRadius * 2).toInt())
        }

        if (mNewBmp == null) {
            //创建一次,避免重复创建,提高速度。
            mNewBmp = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
        }

        val c = Canvas(mNewBmp!!)
        c.drawColor(Color.GRAY) //底色。

        val matrix = Matrix()
        matrix.setScale(mScaleFactor, mScaleFactor)
        matrix.setTranslate((-mCurX) * mScaleFactor + mRadius, (-mCurY) * mScaleFactor + mRadius)

        mDrawable!!.paint.shader.setLocalMatrix(matrix)
        mDrawable!!.draw(c)


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

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


        //绿色圆角矩形框。
        val roundRectPath = Path()
        val roundRectF = RectF(cx - 250, cy - 250, cy + 250, cy + 250)
        roundRectPath.addRoundRect(roundRectF, 25f, 25f, Path.Direction.CW)
        c.drawPath(roundRectPath, mPathPaint3)

        //限定下面切图中Path绘制轨迹路线的区域,超出边界不绘制。
        c.clipRect(roundRectF)

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


        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="40dp"
        android:background="@drawable/ic_launcher_background"
        android:src="@drawable/ic_launcher_foreground" />

</LinearLayout>

所有的绘制轨迹线,都限定在了绿色的圆角矩形框中,超出区域不予绘制。

遗留问题,手指在上图滑动过程中,当滑动到一定区域,下面的切图框中已无太有效的图可以"放大",后续可以填充黑色,表示无效放大。

Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin-CSDN博客文章浏览阅读339次,点赞9次,收藏11次。的基础上,实现一个功能,手指在上面原图的区域滑动,然后在下面的图中以若干放大因子放大显示切块出来的小图,下面切块出来的原图的圆心是手指在上面的触点。同时在下图中复刻上图手指滑动的轨迹。下图的中心圆点用一个圆圈,标识出手指在上图的触点。下图相当于一个放大镜,同时在放大镜图里面显示手指划过的轨迹。遗留一个问题,更好的做法是在下图中只显示圆角矩形切图区域里面的路径,超出圆角矩形切图外的区域,不应该再显示路径。https://blog.csdn.net/zhangphil/article/details/135596459

相关推荐
游戏开发爱好者818 分钟前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码203523 分钟前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥39 分钟前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓1 小时前
[JDBC]元数据
android
独行soc1 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能1 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿1 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市
独行soc2 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
2501_915106322 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview