Android笔记
我的博客
Android笔记
Android笔记
  • Android学习资料
  • Android知识点梳理
  • Android Studio
  • aop
  • UI
    • ViewPager2
    • View
      • View.post()分析
      • 自定义View
        • Canvas使用
        • Paint使用
        • Path使用
        • PathMeasure使用
        • Matrix使用
      • View事件分发
    • TextView
    • EditText
    • 引导页
    • 菜单
    • Toolbar
    • RecyclerView
    • ViewPager
    • BottomSheet
    • 通知
    • CalendarView
    • TimePicker
    • LayoutInfalter
    • shadowlayout
    • 状态栏适配
    • RecyclerView
    • 屏幕适配
  • 组件
    • Activity
    • Intent
    • 服务
      • 服务
      • 绑定服务
      • AIDL
    • Broadcasts
    • Fragment
    • ContentProvider
  • 权限
  • 数据存储
    • 数据和文件存储
    • 将文件保存到外部存储中
    • 将文件保存在内部存储中
    • Android 存储用例和最佳做法
    • 保存键值对数据
  • 编译时注解
    • Untitled
    • Java注解处理器](annotation/annotation-processing.md)
    • JavaPoet 文档翻译
  • 图形和图像
    • Drawable使用
  • 网络
    • WebView
    • OkHttp文档翻译
      • OkHttp使用
      • OkHttp拦截器
    • Retrofit使用
    • Retrofit源码分析
    • HttpURLConnection使用
    • Volley使用
    • Volley源码分析
    • Glide使用
    • Glide源码分析
    • RxJava
  • 插件化
    • 插件化框架
    • VirtualAPK分析
  • 依赖注入
  • 开源库
    • EventBus源码分析
    • Okio概览
    • Okio菜谱
    • Okio
    • OkHttp拦截器
    • OKHttp缓存
    • Okhttp源码分析
  • 集合
    • SparseArray
    • ArrayMap
  • 架构
  • Jetpack
    • databinding adapter
    • databinding坑
    • databinding源码分析
    • Android Data Binding: Let’s Flip This Thing
    • Untitled
    • Lifecycle源码分析
    • ViewModel源码分析
    • LiveData源码分析
  • 音频和视频
    • CameraX使用
    • ExoPlayer
    • GsyVideoPlayer
  • 性能优化
    • 崩溃优化
    • 内存优化
      • LeakCanary如何工作
    • 渲染优化
    • 电池优化
    • 启动优化
    • 网络优化
    • 安装包大小优化
  • NDK开发
  • 系统源码分析
    • Android源码下载
    • Android系统启动
      • init进程启动过程
      • Zygote进程启动过程
      • Zygote进程启动流程
      • SystemServer处理过程
    • 应用程序进程启动过程
      • 应用程序进程启动过程介绍
    • Window
    • WMS
    • WindowManagerService
    • 四大组件的工作过程
      • Activity启动流程分析
      • Activity启动流程
    • ActivityManagerService分析
    • Context详解
    • Binder原理
      • Binder驱动
      • 获取ServiceManager
      • 启动ServiceManager
      • Parcel源码分析
    • Android图形系统概述
    • Choreographer原理
    • Handler使用
    • Handler源码分析
  • 逆向
    • Android抓包
    • 网易云音乐逆向
由 GitBook 提供支持
在本页
  • 基本方法
  • MaskFilter
  • ColorFilter
  • Xfermode
  • PathEffect
  • 着色器
  • BitmapShader
  • LinearGradient
  • RadialGradient
  • SweepGradient
  • ComposeShader
  • 参考
在GitHub上编辑
  1. UI
  2. View
  3. 自定义View

Paint使用

上一页Canvas使用下一页Path使用

最后更新于2年前

基本方法

public void setStrokeWidth(float width)

setStrokeWidth方法用来设置边的宽度。该方法只有在Paint的style设置为STROKE或者FILL_AND_STROKE时起作用。STROKE 的宽度均分两半,一半绘制在圆外,一半绘制在圆内。

Paint mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(128);
mPaint.setColor(getResources().getColor(R.color.orange));//#FF7F00
canvas.drawCircle(192,192,128,mPaint);//绘制带stroke的圆
mPaint.setColor(getResources().getColor(R.color.green));//半透明绿色#2200FF00
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(192,192,128,mPaint);//绘制实心圆

MaskFilter

ColorFilter

Xfermode

Xfermode设置两张图片相交时的模式。Paint提供public Xfermode setXfermode(Xfermode xfermode)来为画笔设置Xfermode。Xfermode有三个子类:AvoidXfermode,PixelXorXfermode和PorterDuffXfermode,前两个类在API 16被遗弃了,所以这里不作介绍。PorterDuffXfermode类主要用于图形合成时的图像过渡模式计算,其概念来自于1984年在ACM SIGGRAPH计算机图形学出版物上发表了“Compositing digital images(合成数字图像)”的Tomas Porter和Tom Duff,合成图像的概念极大地推动了图形图像学的发展,PorterDuffXfermode类名就来源于这俩人的名字组合PorterDuff。

构造函数:

public PorterDuffXfermode(PorterDuff.Mode mode)

PorterDuff.Mode代表混合模式,是一个枚举类型,他的值包括如下:CLEAR、SRC、DST、SRC_OVER、DST_OVER、SRC_IN、DST_IN、SRC_OUT、DST_OUT、SRC_ATOP、DST_ATOP、XOR、DARKEN、LIGHTEN、MULTIPLY、SCREEN。

PathEffect

PathEffect本身是没有实现什么效果的,只是一个简单的基类,不过android.graphics提供了集中常见的效果,系统为了高效的实现不同效果,它们的实现都封装在native中。

  • CornerPathEffect 线条的交汇角效果

  • DashPathEffect 线条的虚线效果

  • DiscretePathEffect 线条的离散

  • PathDashPathEffect 使用Path做虚线的效果(Path可以画图像)

  • ComposePathEffect 组合两种效果

  • SumPathEffect 叠加向后纵效果

着色器

Shader即着色器,负责为定义的图形着色。

Paint提供了public Shader setShader(Shader shader)方法为画笔设置着色器。

android.graphics.Shader类有5个子类:

  • BitmapShader

  • LinearGradient

  • RadialGradient

  • SweepGradient

  • ComposeShader

BitmapShader

BitmapShader就是使用Bitmap对绘制的图形进行着色。

构造函数:

public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)

第一个参数是一个bitmap对象。后两个参数用来设置当图片小于要绘制的图形的尺寸,x轴和y轴图片的绘制方式。

TileMode是一个枚举类型,可使用的类型包括如下:

  • CLAMP:拉伸

  • REPEAT:重复显示图片

  • MIRROR:镜像

x轴和y轴都设置为REPEAT:

mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);//设置画笔样式为填充
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
//绘制矩形
canvas.drawRect(0,0,800,800,mPaint);

x轴和y轴设置都为MIRROR:

mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR));

x轴和y轴设置都为CLAMP:

mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

BitmapShader一个常用的场景就是绘制特殊图形的图片,比如圆形图片和圆角矩形图片。

将上面的例子绘制矩形修改为绘制圆形就可以得到一个圆形图片。

canvas.drawCircle(mBitmap.getWidth()/2, mBitmap.getWidth()/2, mBitmap.getWidth()/2, mPaint);

LinearGradient

LinearGradient利用线性渐变填充图形。LinearGradient具有两个构造函数:

 public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,TileMode tile)

 public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],TileMode tile)

第一个构造函数可以设置两种颜色。

mPaint.setShader(new LinearGradient(0, 0, 100, 100, Color.RED, Color.YELLOW, Shader.TileMode.REPEAT));
canvas.drawRect(0,0,800,800,mPaint);

第二个构造函数可以设置多种颜色。

先定义一个字符串数组:

  <string-array name="rainbow">
    <item>#9400D3</item>
    <item>#4B0082</item>
    <item>#0000FF</item>
    <item>#00FF00</item>
    <item>#FFFF00</item>
    <item>#FF7F00</item>
    <item>#FF0000</item>
  </string-array>
String[] colors = getResources().getStringArray(R.array.rainbow);
mPaint.setShader(new LinearGradient(0, 0, 800, 800, new int[]{
     Color.parseColor(colors[0]),
     Color.parseColor(colors[1]),
     Color.parseColor(colors[2]),
     Color.parseColor(colors[3]),
     Color.parseColor(colors[4]),
     Color.parseColor(colors[5]),
     Color.parseColor(colors[6]),
 }, null, Shader.TileMode.REPEAT));
canvas.drawRect(0,0,800,800,mPaint);

RadialGradient

RadialGradient创建从中心向四周发散的辐射渐变效果。RadialGradient同样有两个构造函数:

public RadialGradient(float centerX, float centerY, float radius,@NonNull int colors[], @Nullable float stops[], @NonNull TileMode tileMode) 

public RadialGradient(float centerX, float centerY, float radius,int centerColor, int edgeColor, @NonNull TileMode tileMode)
mPaint.setShader(new RadialGradient(400, 400,400, new int[] {
    Color.parseColor(colors[0]), Color.parseColor(colors[1]), Color.parseColor(colors[2]),
    Color.parseColor(colors[3]), Color.parseColor(colors[4]), Color.parseColor(colors[5]),
    Color.parseColor(colors[6])
}, null, Shader.TileMode.REPEAT));
canvas.drawRect(0,0,800,800,mPaint);

SweepGradient

SweepGradient可以用来创建360度颜色旋转渐变效果,具体来说颜色是围绕中心点360度顺时针旋转的,起点就是3点钟位置。

SweepGradient有两个构造函数:

public SweepGradient(float cx, float cy,int colors[], float positions[])

public SweepGradient(float cx, float cy, int color0, int color1)

SweepGradient不支持TileMode参数。cx,cy决定了中心点的位置。

mPaint.setShader(new SweepGradient(400, 400, new int[] {
    Color.parseColor(colors[0]), Color.parseColor(colors[1]), Color.parseColor(colors[2]),
    Color.parseColor(colors[3]), Color.parseColor(colors[4]), Color.parseColor(colors[5]),
    Color.parseColor(colors[6])
}, null));
canvas.drawCircle(400,400,400,mPaint);

ComposeShader

ComposeShader它可以将两个Shader按照一定的Xfermode组合起来。

ComposeShader有两个构造函数:

public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode)

public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)

下面我们将一个BitmapShader与LinearGradient进行混合。

BitmapShader使用的图片为下图:

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
LinearGradient linearGradient = new LinearGradient(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), Color.RED, Color.YELLOW, Shader.TileMode.REPEAT);
ComposeShader composeShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(composeShader);
canvas.drawRect(0,0,mBitmap.getWidth(),mBitmap.getHeight(),mPaint);

参考

开源项目、本质都是利用BitmapShader实现的。

CircleImageView
android-shape-imageview
各个击破搞明白PorterDuff.Mode
Shader
Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
Android Paint 浅坑—— Style 模式
黄色的圆先绘制是目标图,蓝色的矩形后绘制是目标图