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

news2024/11/11 22:17:45

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

 

在  Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin-CSDN博客 基础上,限定下面切图的绘制区域,超出绿色区域的轨迹线不再绘制。

 

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

 

 

b9a13c8d53ba4009b1973a0662120e03.png

 

 

e356425badc64563ac4ad05c206a01c8.png

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

 

 

efe0b152586c4a05a27f1ed8ca2d0fa0.png

 

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

 

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1398217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

esp32-cam 视频查看教程

一、环境配置 查看以前教程 环境配置 建议使用1.0.6 二、安装基于esp32 cam的代码 资料地址&#xff1a; https://pan.baidu.com/s/1Y9-rLLmAKPYzBDcrEyuGMw 提取码&#xff1a;2022 下载后打开文件下的程序 下载程序 三、获取视频url 在arduino 看不到串口打印的信息&a…

Android studio 简单登录APP设计

一、登录界面: 二、xml布局设计: <LinearLayoutandroid:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:layout_editor_absoluteX="…

assignment1——KNN

KNN 整体思路 加载数据集CIFAR10并随机展示部分数据构建KNearestNeighbor分类器&#xff0c;计算测试集每张图片的每个像素点与训练集每张图片的每个像素点的距离。将图片转化为数组。在测试集使用compute_distances_one_loop&#xff0c;compute_distances_no_loops&#xf…

挑战杯参赛总结-时间序列预测

参赛任务&#xff1a; 目标&#xff1a;针对中国各个市区的不同年份二氧化碳排放量&#xff0c;预测未来年份的二氧化碳排放量。 不同与之前我学习过的波士顿房价预测机器学习-波士顿房价预测-CSDN博客 房价预测是通过学习与房价有关的很多特征&#xff0c;训练出一个模型来预…

UV胶水粘接尼龙聚酰胺类聚合物PA有哪些优势呢?

使用UV胶水&#xff08;紫外线固化胶水&#xff09;粘接尼龙聚酰胺类聚合物&#xff08;PA&#xff09;具有一些优势&#xff0c;这些优势包括&#xff1a; 1.快速固化&#xff1a; UV胶水是一种紫外线固化的胶水&#xff0c;它可以在短时间内迅速固化。这使得粘接过程非常快速…

02-编程猜谜游戏

本章通过演示如何在实际程序中使用 Rust&#xff0c;你将了解 let 、 match 、方法、关联函数、外部crate等基础知识。 本章将实现一个经典的初学者编程问题&#xff1a;猜谜游戏。 工作原理如下&#xff1a;程序将随机生成一个介于 1 和 100 之间的整数。然后&#xff0c;程序…

Pycharm详细安装 配置教程

继上次安装完Anaconda之后&#xff0c;现在更新最新版本的pycharm的安装和使用教程~~~ Anaconda&#xff1a;是一个开源的Python发行版本&#xff0c;其中包含了conda、Python等180多个科学包及其依赖项。【Anaconda和Pycharm详细安装 配置教程_anconda安装时clear the packag…

音频筑基:时延、帧长选取的考量

音频筑基&#xff1a;时延、帧长选取的考量 帧长与时延的关系帧长变化的影响参考资料 音频算法中&#xff0c;时延和音频帧长的选择通常是个需要平衡的参数&#xff0c;这里分析下背后的考量因素。 帧长与时延的关系 一般来说&#xff0c;帧长是音频算法端到端时延的子集&…

【Linux】Linux 系统编程——touch 命令

文章目录 1.命令概述2.命令格式3.常用选项4.相关描述5.参考示例 1.命令概述 在**Linux 中&#xff0c;每个文件都与时间戳相关联&#xff0c;每个文件都存储了上次访问时间、**上次修改时间和上次更改时间的信息。因此&#xff0c;每当我们创建新文件并访问或修改现有文件时&a…

设计模式篇章(4)——十一种行为型模式

这个设计模式主要思考的是如何分配对象的职责和将对象之间相互协作完成单个对象无法完成的任务&#xff0c;这个与结构型模式有点像&#xff0c;结构型可以理解为静态的组合&#xff0c;例如将不同的组件拼起来成为一个更大的组件&#xff1b;而行为型更是一种动态或者具有某个…

【Python爬虫】项目案例讲解,一步步教你爬取淘宝商品数据!

前言 随着互联网时代的到来&#xff0c;人们更加倾向于互联网购物&#xff0c;某宝又是电商行业的巨头&#xff0c;在某宝平台中有很多商家数据&#xff0c;今天带大家使用pythonselenium工具获取这些公开的商家数据 环境介绍&#xff1a; python 3.6pycharmseleniumcsvtime…

快来体验,免费一步步教你,零代码,无需服务器,一键部署你的大模型!

今天给大家分享一个项目&#xff0c;零代码、无需服务器&#xff0c;直接 一键部署 你的大模型项目。 废话不多说&#xff0c;项目就是它&#xff1a; 我们看到目前已支持&#xff1a; ChatGPT-Next-Web&#xff1a;一键免费部署你的私人 ChatGPT、谷歌Gemini 网页应用AutoGPT-…

安防监控系统EasyCVR平台用户调用设备参数,信息不返回是什么原因?

安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;平台能在复杂的网络环境中&#xff08;专网、局域网、广域网、VPN、公网等&#xff09;将前端海量的设备进行统一集中接入与视频汇聚管理&#xff0c;平台支持设备通过4G、5G、WIFI、有…

Leetcoder Day9|栈与队列part01

语言&#xff1a;Java/C 目录 理论基础 C 栈 队列 Java 栈 队列 ​编辑 232.用栈实现队列 225. 用队列实现栈 Queue Deque 今日心得 理论基础 又是考研时数据结构里接触到的老朋友&#xff0c;栈是先进后出&#xff0c;队列是先进先出。 C 现在刷题除了思路还…

【算法与数据结构】494、LeetCode目标和

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题和这道题【算法与数据结构】1049、LeetCode 最后一块石头的重量 II类似&#xff0c;同样可以转换成…

Windows系统使用手册

点击前往查看&#x1f517;我的博客文章目录 Windows系统使用手册 文章目录 Windows系统使用手册Windows10解决大小核调度问题Windows系统安装软件Windows系统Typora快捷键Windows系统压缩包方式安装redisWindows安装dockerWindows系统的docker设置阿里源Windows系统下使用doc…

JAVA正则表达式第二个作用:爬取

目录 本地数据爬取&#xff1a; 本地爬取练习&#xff1a; 网络爬取&#xff1a; ----- 以下为均本地数据爬取&#xff1a; 带条件爬取 贪婪爬取和非贪婪爬取&#xff1a; 例题 1&#xff1a;使获取 1 为不贪婪 *例题 2&#xff1a;使获取 0、1 都为不贪婪 之前介绍了正…

mp4文件可以转成mp3音频吗

现在是个非常流行刷短视频一个年代&#xff0c;刷短视似乎成了人们休闲娱乐的一种方式&#xff0c;在日常刷短视频过程中&#xff0c;肯定会有很多同学被短视频 bgm 神曲洗脑&#xff0c;比如很多被网红翻唱带火的歌曲&#xff0c;例如其中"不负人间”&#xff0c;就是其中…

从零开始,自己搭建一个autonomous mobile robot做gazebo仿真(1):mobile robot建模与添加差速控制器

这样一个简单的mobile robot模型 首先写xacro文件&#xff0c;创建 link joint transmission <?xml version"1.0"?> <robot xmlns:xacro"http://www.ros.org/wiki/xacro" name"whill_modelc" ><xacro:property name"PI&q…

Unity导出Android项目踩坑记录

导出的时候需要注意以下地方的配置&#xff1a; 1、buildSetting-> 设置ExportProject 2、buildsetting ->playerSetting ->设置IL2CPP 3、设置ndk edit->preferences->external tools->ndk 如果unity的ndk版本和android项目里的ndk版本不一致会报错&…