当前位置: 首页 > news >正文

Android图片涂鸦,Kotlin(1)

Android图片涂鸦,Kotlin(1)

 

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PointF
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageViewclass PaintView @JvmOverloads constructor(context: Context?,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : AppCompatImageView(context!!, attrs, defStyleAttr) {class DrawPath {var id: Long = 0Lvar path: Path? = nullvar paint: Paint? = nullvar points = ArrayList<PointF>()}private var mPaint: Paint? = nullprivate var mPath: Path? = nullprivate var mDownX = 0fprivate var mDownY = 0fprivate var mTempX = 0fprivate var mTempY = 0f//默认的画笔宽度private var mPaintWidth = 10//默认画笔的颜色private var mColor = Color.REDprivate val mDrawPathList: ArrayList<DrawPath>?private val mSavePathList: ArrayList<DrawPath>?companion object {var WIDTH_INCREMENT = 15const val TAG = "PaintView"}init {mDrawPathList = ArrayList()mSavePathList = ArrayList()initPaint()}private fun initPaint() {mPaint = Paint()mPaint?.color = mColormPaint?.isAntiAlias = truemPaint?.strokeWidth = mPaintWidth.toFloat()mPaint?.style = Paint.Style.STROKE}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)if (!mDrawPathList.isNullOrEmpty()) {for (drawPath in mDrawPathList) {if (drawPath.path != null) {canvas.drawPath(drawPath.path!!, drawPath.paint!!)}drawPath.points.forEach {Log.d(TAG, "onDraw ${drawPath.id} ${it.x} ${it.y}")}}}}override fun onTouchEvent(event: MotionEvent): Boolean {when (event.action) {MotionEvent.ACTION_DOWN -> {Log.d(TAG, "ACTION_DOWN ${event.x} ${event.y}")mDownX = event.xmDownY = event.y//每次手指点下去作为一条新路径。mPath = Path()mPath?.moveTo(mDownX, mDownY)val drawPath = DrawPath()drawPath.id = System.currentTimeMillis()drawPath.paint = mPaintdrawPath.path = mPathmDrawPathList?.add(drawPath)//新一轮绘制开始,保存点。drawPath.points.add(PointF(event.x, event.y))invalidate()mTempX = mDownXmTempY = mDownY}MotionEvent.ACTION_MOVE -> {//Log.d(TAG, "ACTION_MOVE ${event.x} ${event.y}")val moveX = event.xval moveY = event.ymPath?.quadTo(mTempX, mTempY, moveX, moveY)mDrawPathList?.filter {it.path == mPath}?.forEach {it.points.add(PointF(event.x, event.y))}invalidate()mTempX = moveXmTempY = moveY}//每次手指抬起重置画笔,不然画笔会保存之前设置的属性会引起bug。MotionEvent.ACTION_UP -> {Log.d(TAG, "ACTION_UP ${event.x} ${event.y}")initPaint()}}return true}/*** 撤销。*/fun undo() {if (mDrawPathList != null && mDrawPathList.size >= 1) {mSavePathList?.add(mDrawPathList[mDrawPathList.size - 1])mDrawPathList.removeAt(mDrawPathList.size - 1)invalidate()}}/*** 反撤销,重新生效。*/fun reundo() {if (!mSavePathList.isNullOrEmpty()) {mDrawPathList?.add(mSavePathList[mSavePathList.size - 1])mSavePathList.removeAt(mSavePathList.size - 1)invalidate()}}/*** 画笔颜色。** @param color*/fun setPaintColor(color: Int) {this.mColor = colormPaint?.color = this.mColor}/*** 画笔的宽度。*/fun setPaintWidth(size: Int) {mPaintWidth += sizemPaint?.strokeWidth = mPaintWidth.toFloat()}/*** 放大,改变画笔的宽度。线条变粗。*/fun enlargePaintWidth() {mPaintWidth += WIDTH_INCREMENTmPaint?.strokeWidth = mPaintWidth.toFloat()}fun getDrawPath(): ArrayList<DrawPath>? {return mDrawPathList}
}

 

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><com.pkg1115.PaintViewandroid:id="@+id/paint_view"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter"android:src="@mipmap/p1"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><RelativeLayoutandroid:id="@+id/rl_left"android:layout_width="100dp"android:layout_height="wrap_content"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><Buttonandroid:id="@+id/btn_undo"android:layout_width="match_parent"android:layout_height="60dp"android:text="撤销" /><Buttonandroid:id="@+id/btn_red"android:layout_width="match_parent"android:layout_height="60dp"android:layout_below="@id/btn_undo"android:text="红色" /><Buttonandroid:id="@+id/btn_green"android:layout_width="match_parent"android:layout_height="60dp"android:layout_below="@id/btn_red"android:text="绿色" /><Buttonandroid:id="@+id/btn_enlarge"android:layout_width="match_parent"android:layout_height="60dp"android:layout_below="@id/btn_green"android:text="放大" /></RelativeLayout></androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

 

Android图形图像处理:添加涂鸦文字_android 在图片上涂鸦-CSDN博客文章浏览阅读2k次。先看运行效果: 关键的PaintView:package com.zhangphil;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graph..._android 在图片上涂鸦https://blog.csdn.net/zhangphil/article/details/87810653

 

相关文章:

Android图片涂鸦,Kotlin(1)

Android图片涂鸦&#xff0c;Kotlin&#xff08;1&#xff09; import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.graphics.PointF import android.…...

upload-labs(1-17关攻略详解)

upload-labs pass-1 上传一个php文件&#xff0c;发现不行 但是这回显是个前端显示&#xff0c;直接禁用js然后上传 f12禁用 再次上传&#xff0c;成功 右键打开该图像 即为位置&#xff0c;使用蚁剑连接 连接成功 pass-2 源码 $is_upload false; $msg null; if (isse…...

《 机器人基础 》期末试卷(A)

一、填空题&#xff08;30分&#xff0c;每空2分&#xff09; 1. 按照相机的工作方式&#xff0c;机器人常用相机分为1&#xff09;__ 单目摄像头 2&#xff09;__ 双目摄像头 _ 3&#xff09;_深度摄像头_ 三类。 2. 度量地图强调…...

Azure Machine Learning - Azure AI 搜索中的矢量搜索

矢量搜索是一种信息检索方法&#xff0c;它使用内容的数字表示形式来执行搜索方案。 由于内容是数字而不是纯文本&#xff0c;因此搜索引擎会匹配与查询最相似的矢量&#xff0c;而不需要匹配确切的字词。本文简要介绍了 Azure AI 搜索中的矢量支持。 其中还解释了与其他 Azure…...

3 redis实现一个消息中间件

使用list实现一个队列&#xff0c;可以从左侧入队&#xff0c;也可以从右侧入对 即可以从左侧读取&#xff0c;也可以从右侧读取 1、Lindex Lindex 命令用于通过索引获取列表中的元素 也可以使用负数下标&#xff0c;以 -1 表示列表的最后一个元素&#xff0c; -2 表示列表的…...

js添加dom到指定div之后,并给添加的dom类名,然后设置其样式,以及el-popover层级z-index过高问题解决。

遇到一个需求,Vue项目做一个表格,要求表头与表格内容分开,如下效果所示,表头与表格有个高度间隔边距(箭头所示),因为默认我们的el-table的表头与内容是一起的: 思路:通过querySelector获取el-table__header-wrapper元素,通过createElement创建一个div,通过 newElem…...

C语言结构体

#include <stdio.h> #include <string.h> #include <stdlib.h>//struct Student_s { // int num; // char name[20]; // char gender; // int age; // float Chinese; // float Math; // float English; // char addr[30]; //}; //最后的分号一定要写&#x…...

【Python大数据笔记_day10_Hive调优及Hadoop进阶】

hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时&#xff0c;不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率&#xff0c;或帮助定位问…...

React经典初级错误

文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者&#xff0c;我们创造bug&#xff0c;传播bug&#xff0c;毫不留情地消灭bug&#xff0c;在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案&#xff0c;感兴…...

C# System.Array.CopyTo() 和 System.Array.Clone() 有什么区别

System.Array.CopyTo() 和 System.Array.Clone() 是用于数组复制的两种不同方法&#xff0c;它们在实现和用途上有一些区别。 System.Array.CopyTo() 方法&#xff1a; CopyTo() 方法用于将数组的元素复制到另一个数组。它是 Array 类的实例方法&#xff0c;可以用于复制一个…...

Stable Diffusion 启动时 got an unexpected keyword argument ‘socket_options‘ 错误解决

Stable Diffusion 启动时 got an unexpected keyword argument socket_options 错误解决 问题解决方法 问题 Launching Web UI with arguments: Traceback (most recent call last):File "launch.py", line 48, in <module>main()File "launch.py"…...

CSS 文本属性篇

文字颜色 属性名&#xff1a;color作用&#xff1a;控制文字的颜色可选值&#xff1a; 1.颜色名 color: blue; 2.rgb或rgba color:rgb(132, 220, 254); color:rgba(132, 220, 254,0.5); 3.hex或hexa&#xff08;十六进制&#xff09; color:#0078d4; color:#0078d48b; 4.hsl或h…...

Activiti,Apache camel,Netflex conductor对比,业务选型

Activiti,Apache camel,Netflex conductor对比&#xff0c;业务选型 1.activiti是审批流&#xff0c;主要应用于人->系统交互&#xff0c;典型应用场景&#xff1a;请假&#xff0c;离职等审批 详情可见【精选】activti实际使用_activiti通过事件监听器实现的优势_记录点滴…...

pythom导出mysql指定binlog文件

要求 要求本地有py环境和全局环境变量 先测试直接执行binlog命令执行命令 Windows 本地直接执行命令 # E:\output>E:\phpstudy_pro\Extensions\MySQL5.7.26\bin\mysqlbinlog binglog文件地址 # --no-defaults 不限制编码 # -h mysql链接地址 # -u mysql 链接名称 # -p m…...

TDengine 跨版本迁移实战

TDengine 3.0 已经退出了近一年&#xff0c;目前已经到了 3.2 版本。很遗憾的是 2.x 和 3.x 之间的数据文件不兼容。 如果向从 2.x 升级到 3.x 只能选择数据迁移的方式。 目前数据迁移有三种方法&#xff1a; 使用官方推荐工具 taosx。使用 taosdump 工具。自己写程序。 迁移…...

FPGA设计时序约束八、others类约束之Set_Case_Analysis

目录 一、序言 二、Set Case Analysis 2.1 基本概念 2.2 设置界面 2.3 命令语法 2.4 命令示例 三、工程示例 四、参考资料 一、序言 在Vivado的时序约束窗口中&#xff0c;存在一类特殊的约束&#xff0c;划分在others目录下&#xff0c;可用于设置忽略或修改默认的时序…...

xftp连接wsl2

在WSL中默认是没有安装OpenSSH&#xff0c;需要自己安装。 安装 sudo apt update sudo apt install openssh-server检查是否安装成功 ssh -V配置ssh sudo vim /etc/ssh/ssh_config设置端口 Port 22启动ssh服务 sudo service ssh startxftp连接 主机地址&#xff1a;127.…...

Cross-View Transformers for Real-Time Map-View Semantic Segmentation 论文阅读

论文链接 Cross-View Transformers for Real-Time Map-View Semantic Segmentation 0. Abstract 提出了 Cross-View Transformers &#xff0c;一种基于注意力的高效模型&#xff0c;用于来自多个摄像机的地图视图语义分割使用相机感知的跨视图注意机制隐式学习从单个相机视…...

MySQL InnoDB 引擎底层解析(一)

6. InnoDB 引擎底层解析 MySQL 对于我们来说还是一个黑盒&#xff0c;我们只负责使用客户端发送请求并等待服务器返回结果&#xff0c;表中的数据到底存到了哪里&#xff1f;以什么格式存放的&#xff1f;MySQL 是以什么方式来访问的这些数据&#xff1f;这些问题我们统统不知…...

redis安装(Windows和linux)

如何实现Redis安装与使用的详细教程 Redis 简介 Redis是一个使用C语言编写的开源、高性能、非关系型的键值对存储数据库。它支持多种数据结构&#xff0c;包括字符串、列表、集合、有序集合、哈希表等。Redis的内存操作能力极强&#xff0c;其读写性能非常优秀&#xff0c;且…...

【LeetCode刷题-树】--1367.二叉树中的链表

1367.二叉树中的链表 方法&#xff1a;枚举 枚举二叉树中的每个节点为起点往下的路径是否与链表相匹配的路径&#xff0c;为了判断是否匹配设计了一个递归函数dfs(root,head),其中root表示当前匹配到的二叉树节点&#xff0c;head表示当前匹配到的链表节点&#xff0c;整个函数…...

【嵌入式 – GD32开发实战指南(ARM版本)】第2部分 外设篇 - 第3章 温度传感器DS18B20

1 理论分析 1.1 DS18B20概述 DS18B20 是 DALLAS 最新单线数字温度传感器,新的"一线器件"体积更小、适用电压更宽、更经济。Dallas 半导体公司的数字化温度传感器 DS1820 是世界上第一片支持 "一线总线"接口的温度传感器。 DS18B20采用的单总线协议,也…...

基于spring gateway 的静态资源缓存实现

由于子项目比较多&#xff0c;子项目都是通过嵌套的方式实现的。就会导致子页面加载比较慢&#xff0c;影响客户体验 实现思路&#xff08;AI搜的--!&#xff09;: 1、通过spring boot缓存实现静态资源缓存 2、在gateway过滤器&#xff0c;对静态资源进行缓存 直接上代码&a…...

SDUT OJ《算法分析与设计》搜索算法

A - 子集和问题 Description 子集和问题的一个实例为〈S,t〉。其中&#xff0c;S{ x1 &#xff0c; x2 &#xff0c;…&#xff0c;xn }是一个正整数的集合&#xff0c;c是一个正整数。子集和问题判定是否存在S的一个子集S1&#xff0c;使得&#xff1a; 。 试设计一个解子…...

【NI-DAQmx入门】校准

1.设备定期校准的理由 随着时间的推移电子器件的特性会发生自然漂移&#xff0c;可能会导致测量结果的不准确性。防止出现良品和差品筛选出错的情况满足行业国际标准降低设备出现故障的风险使测量结果更具备参考性 2.查找NI设备的校准间隔。 定期校准会使DAQ设备的精度保持在…...

C语言链表

head.h typedef struct Node_s{int data; //数据域struct Node_s *pNext; //指针域 } Node_t, *pNode_t;void headInsert(pNode_t *ppHead, pNode_t *ppTail, int data); void print(pNode_t pHead); void tailInsert(pNode_t *ppHead, pNode_t *ppTail, int data); void sort…...

LabVIEW进行MQTT通信及数据解析

需求&#xff1a;一般通过串口的方式进行数据的解析&#xff0c;但有时候硬件的限制&#xff0c;没法预留串口&#xff0c;那么如何通过网络的方式特别是MQTT数据的通信及解析 解决方式&#xff1a; 1.MQTT通信控件&#xff1a; 参考开源的mqtt-LabVIEW https://github.com…...

基于DOTween插件实现金币飞行到指定位置功能

文章目录 前言一、DOTween是什么&#xff1f;二、使用步骤1.导入DOTween插件在Unity官方插件商店找到DOTween插件导入DOTween插件启用DOTween插件 2.代码逻辑金币飞行代码控制飞行效果代码 3.物体配置1.物体上装配CoinEffect脚本2.在金币预制体上装配FlyControl脚本 三、效果展…...

python-opencv 培训课程作业

python-opencv 培训课程作业 作业一&#xff1a; 第一步&#xff1a;读取 res 下面的 flower.jpg&#xff0c;读取彩图&#xff0c;并用 opencv 展示 第二步&#xff1a;彩图 -> 灰度图 第三步&#xff1a;反转图像&#xff1a;最大图像灰度值减去原图像&#xff0c;即可得…...

【Go入门】并发

【Go入门】并发 有人把Go比作21世纪的C语言&#xff0c;第一是因为Go语言设计简单&#xff0c;第二&#xff0c;21世纪最重要的就是并行程序设计&#xff0c;而Go从语言层面就支持了并行。 goroutine goroutine是Go并行设计的核心。goroutine说到底其实就是协程&#xff0c;…...