Android中的自绘View的那些事儿(八)之 Paint的高级用法

2023-11-19

我们在《Android中的自绘View的那些事儿(一)》中简单介绍过Paint和Canvas的一些常用方法和实例使用。其中,一句话提到Paint中有方法:setStrokeCapsetStrokeJoinsetPathEffect。今天我们就来针对这三个方法来进一步讲解其使用效果。

setStrokeCap

setStrokeCap(Paint.Cap cap);当Paint的setStyle为STROKE或FILL_OR_STROKE时,设置画笔的线冒样式,值有:Cap.BUTTCap.ROUND(圆形样式)和Cap.SQUARE(方形样式)。

示例:

public class MyView extends View {

    private Paint mPaint;

    public MyView(Context context) {
        this(context, null, 0);
    }
    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(0xffff0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawLine(100, 100, 500, 100, mPaint);

        mPaint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawLine(100, 200, 500, 200, mPaint);

        mPaint.setStrokeCap(Paint.Cap.SQUARE);
        canvas.drawLine(100, 300, 500, 300, mPaint);
    }
}

效果:


setStrokeJoin

setStrokeJoin(Paint.Join join);当setStyle为STROKE或FILL_OR_STROKE时,设置线段连接处样式,值有:Join.MITER(结合处为锐角)、Join.Round(结合处为圆弧)、Join.BEVEL(结合处为直线) 。

示例:

public class MyView extends View {

    private Paint mPaint;

    public MyView(Context context) {
        this(context, null, 0);
    }
    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(0xffff0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setStrokeJoin(Paint.Join.MITER);
        Path pathA  = new Path();
        pathA.moveTo(100,200);
        pathA.lineTo(500,200);
        pathA.lineTo(500,300);
        canvas.drawPath(pathA, mPaint);

        mPaint.setStrokeJoin(Paint.Join.ROUND);
        Path pathB  = new Path();
        pathB.moveTo(100,500);
        pathB.lineTo(500,500);
        pathB.lineTo(500,600);
        canvas.drawPath(pathB, mPaint);

        mPaint.setStrokeJoin(Paint.Join.BEVEL);
        Path pathC  = new Path();
        pathC.moveTo(100,800);
        pathC.lineTo(500,800);
        pathC.lineTo(500,900);
        canvas.drawPath(pathC, mPaint);
    }
}

效果:


setPathEffect

setPathEffect(PathEffect effect);设置路径样式,其中传值是PathEffect的子类。其中已知子类有:CornerPathEffectDashPathEffectDiscretePathEffectPathDashPathEffectComposePathEffectSumPathEffect

CornerPathEffect(圆角效果)

圆角效果就是拐角处变成圆形,CornerPathEffect(float radius)构造函数接收一个浮点值,它代表拐角处圆的半径。

DashPathEffect(虚线效果)

虚线效果,DashPathEffect(float intervals[], float phase)构造函数接收两个值,第一个参数intervals[]表示组成虚线的一段线段的长度,然后根据此线段来作一个循环组成最终一整条线段。如:new float[] { 10, 5 };则表示虚线中,可见长度是10,间隔长度是5。intervals[]还有两个限制条件:长度必须大于等于2;个数必须是偶数。第二个参数phase表示开始绘制的偏移值,一般为0则可。

DiscretePathEffect(离散效果)

离散效果就是将原来路径分隔成定长的线段,然后将每条线段随机偏移一段位置。DiscretePathEffect(float segmentLength, float deviation)构造函数接收两个值,第一个参数segmentLength表示将原来的路径切成多长的线段。第二个参数deviation表示被切成的每个小线段的可偏移距离。听起来是不是觉得很抽象?不用紧张,稍后看实例效果例会清晰了。

PathDashPathEffect(印章效果)

印章效果就是用另一个路径图案作为印章,沿着线段路径像印章一样盖着连接。PathDashPathEffect(Path shape, float advance, float phase,Stylestyle)构造函数接收四个值,shape表示印章路径;advance表示两个印章之间的距离;phase表示绘制偏移距离;最后style表示遇到转角时的过度效果,值有:Style.ROTATE(旋转印章过渡转角)、Style.MORPH(变形印章过渡转角)和 Style.TRANSLATE(位移印章过渡转角)

ComposePathEffect(合并效果)和 SumPathEffect(叠加效果)

合并效果是把两种样式合并成一种形式。而叠加效果则是直接的把两种样式放在一起。

 

示例:

public class MyView extends View {

    private Paint mPaint;

    public MyView(Context context) {
        this(context, null, 0);
    }
    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(0xffff0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 圆角效果
        mPaint.setPathEffect(new CornerPathEffect(100));
        Path pathA  = new Path();
        pathA.moveTo(100,10);
        pathA.lineTo(500,10);
        pathA.lineTo(100,110);
        canvas.drawPath(pathA, mPaint);

        // 虚线效果
        mPaint.setPathEffect(new DashPathEffect(new float[] { 20, 10 }, 0));
        Path pathB  = new Path();
        pathB.moveTo(100,160);
        pathB.lineTo(500,160);
        pathB.lineTo(100,260);
        canvas.drawPath(pathB, mPaint);

        // 离散效果
        mPaint.setPathEffect(new DiscretePathEffect(5, 10));
        Path pathC  = new Path();
        pathC.moveTo(100,310);
        pathC.lineTo(500,310);
        pathC.lineTo(100,410);
        canvas.drawPath(pathC, mPaint);

        // 印章效果
        Path stampPath  = new Path();
        stampPath.moveTo(0,20);
        stampPath.lineTo(10,0);
        stampPath.lineTo(20,20);
        stampPath.close();
        mPaint.setPathEffect(new PathDashPathEffect(stampPath, 20, 0, PathDashPathEffect.Style.TRANSLATE));
        Path pathD  = new Path();
        pathD.moveTo(100,460);
        pathD.lineTo(500,460);
        pathD.lineTo(100,560);
        canvas.drawPath(pathD, mPaint);

        // 合并效果
        mPaint.setPathEffect(new ComposePathEffect(new CornerPathEffect(100),  new DashPathEffect(new float[] { 20, 10 }, 0)));
        Path pathE  = new Path();
        pathE.moveTo(100,610);
        pathE.lineTo(500,610);
        pathE.lineTo(100,710);
        canvas.drawPath(pathE, mPaint);

        // 叠加效果
        mPaint.setPathEffect(new SumPathEffect(new CornerPathEffect(100),  new DashPathEffect(new float[] { 20, 10 }, 0)));
        Path pathF  = new Path();
        pathF.moveTo(100,760);
        pathF.lineTo(500,760);
        pathF.lineTo(100,860);
        canvas.drawPath(pathF, mPaint);
    }
}

效果:

 


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中的自绘View的那些事儿(八)之 Paint的高级用法 的相关文章

随机推荐

  • qsort(),sort()排序函数

    一 qsort 函数 功 能 使用快速排序例程进行排序 头文件 stdlib h 用 法 void qsort void base int nelem int width int fcmp const void const void 参数
  • 面试题六道-2022-1-6

    CopyOnWriteArrayList的底层原理是怎样的 1 首先CopyOnWriteArraylist内部也是用过数组来实现的 在向CopyOnWriteArrayLlist添加元素时 会复制一个新的数组 写操作在新数组上进行 读操作
  • 尚筹网-前台-会员系统(springboot,springcloud 实战)

    总目标 环境搭建 会员登录注册 发起众筹项目 展示众筹项目 支持众筹项目 订单 支付 1 会员系统架构 1 1 架构图 1 2 需要创建的工程 父工程 聚合工程 shangcouwang01 member parent 唯一的pom工程 注
  • 强化学习 9 —— DQN 改进算法 DDQN、Dueling DQN 详解与tensorflow 2.0实现

    上篇文章强化学习 详解 DQN 算法介绍了 DQN 算法 但是 DQN 还存在一些问题 本篇文章介绍针对 DQN 的问题的改进算法 一 Double DQN 算法 1 算法介绍 DQN的问题有 目标 Q 值 Q Target 计算是否准确
  • VUE常用UI组件插件及框架-vue前端UI框架收集

    UI组件及框架 element 饿了么出品的Vue2的web UI工具套件 mint ui Vue 2的移动UI元素 iview 基于 Vuejs 的开源 UI 组件库 Keen UI 轻量级的基本UI组件合集 vue material 通
  • Java jar包启动及停止

    此处以SpringBoot maven工程为基础 基于Windows系统 工程开发好后 打包成jar包 一 启动jar包 在包所在的目录下运行cmd命令 执行命令 java jar jar包名 二 停止 1 用管理员打开cmd命令窗口 2
  • Java安全之SSL/TLS

    在前面所讲到的一些安全技术手段如 消息摘要 加解密算法 数字签名和数据证书等 一般都不会由开发者直接地去使用 而是经过了一定的封装 甚至形成了某些安全协议 再暴露出一定的接口来供开发者使用 因为直接使用这些安全手段 对开发者的学习成本太高
  • 初学树莓派——(六)树莓派安装OpenCV及USB摄像头配置

    目录 1 安装OpenCV 1 1前言 1 2换源及源内容更新 1 3安装依赖 1 4下载whl包 1 5安装OpenCV 1 6检查安装 2 USB摄像头配置 同时检查OpenCV安装情况 2 1前言 2 2Python调用cv2库来检查
  • sem_init函数用法

    sem init函数 sem init函数是Posix信号量操作中的函数 sem init 初始化一个定位在 sem 的匿名信号量 value 参数指定信号量的初始值 pshared 参数指明信号量是由进程内线程共享 还是由进程之间共享 如
  • 最优化算法概述以及常见分类

    1 最优化问题概述 通俗的来说 最优化问题就是在一定的条件约束下 使得效果最好 最优化问题是一种数学问题 是研究在给定的约束之下如何求得某些因素的量 来使得某一指标达到最优的学科 工程设计中最优化问题的一般说法是 选择一组参数 在满足一系列
  • 数据结构笔记(六)——散列(Hash Table)之散列函数(1)

    散列表 hash table 的实现叫做散列 hashing 这是以常数平均时间O 1 进行插入 删除和查找的技术 散列表没有顺序 需要元素间排序信息的操作 如findMin findMax不会得到有效支持 就是这东西不是这么用的 你可以实
  • RocketMq顺序发送消息

    错乱消息出现的原因 1 在RocketMq为啥消息不是按照顺序来的呢 首先您需要了解 队列是一个先进先出的一个数据的结构 生产者 您可以将topic理解为里面有一个一个的队列 你将一个消息发送到topic的时候 当前的消息不一定是往当前的这
  • win 10 搭建FTP服务,并使用的FTP进行传输文件(很详细)

    1 安装IIS工具 打开控制面板 点击 程序 点击 启用或关闭Windows功能 找到 internet information services 全部都选上 如下图 点击 确定 会出现以下页面 点击 关闭 即可 2 设置开机启动FTP服务
  • 高光谱图像中的Hughes(休斯)现象

    注解 在高光谱图像的分析中 随着参与运算波段数目的增加 分类精度 先增后降 的现象 场景 高光谱影像 由于维数的大幅度增加 在深度学习中 可以理解成模型提取的特征维数的增加 导致用于参数训练的所需样本数也急剧增加 如果样本数过少 那么估计出
  • Fiddler 详尽教程与抓取移动端数据包

    转载自 http blog csdn net qq 21445563 article details 51017605 阅读目录 1 Fiddler 抓包简介 1 字段说明 2 Statistics 请求的性能数据分析 3 Inspecto
  • C++面试题目集合(持续跟新)

    与我前面写的C语言进阶知识点遥相呼应 这才是C 面试 网上的面试题有些太简单了 C 面试题目最多集中在对象的内存模型 记住了 如果用c c 内存都不清楚 还写个屁的程序 1 C 的虚函数是怎样实现的 C 的虚函数使用了一个虚函数表来存放了每
  • 我的世界服务器物品不掉落指令是什么,我的世界死亡物品怎么不掉落 我的世界物品不掉落指令...

    我的世界死亡不了多指令是gamerulekeepInventorytrue 玩家们要注意我的世界死亡不掉落指令默认是关闭状态的哦 死亡不掉落指令在 我的世界 游戏里面就是当玩家们死亡以后仍然保留其物品栏中的所有物品 包括附魔死亡消失魔咒的物
  • 安装WSL + zsh & Pure (ZSH prompt) 美化【Windows11】

    文章目录 前言 WSL 安装 ZSH 安装ZSH Pure ZSH prompt 安装插件 下载插件 编辑配置文件 插件作用 啊 PS 如果在启动过程中提示 请启用虚拟机平台 windows 功能并确保在 bios 中启用虚拟化 前言 之前
  • 数据分析36计(28):Python 使用 Flask+Docker, 100行代码内实现机器学习实时预测​...

    本文的想法是快速轻松地构建 Docker 容器 Python 以使用 Flask 实现机器学习模型执行在线预测 API 我们将使用 Docker 和 Flask RESTful 实现线性判别分析和多层感知器神经网络模型的实时预测 项目包括的
  • Android中的自绘View的那些事儿(八)之 Paint的高级用法

    我们在 Android中的自绘View的那些事儿 一 中简单介绍过Paint和Canvas的一些常用方法和实例使用 其中 一句话提到Paint中有方法 setStrokeCap setStrokeJoin 和 setPathEffect 今