Android-高级-UI-进阶之路-(五)-看完该篇文章-Canvas-你应该会了

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

canvas.drawColor(Color.RED)
//2.
// canvas.drawARGB(0xff,0xff,0,0x00)
//3.
// canvas.drawRGB(0xff,0x00,0x00)
}

三个 API 效果一样

绘制直线

//startX,y 起点坐标
//stopX,y 终点坐标
//paint 画笔
void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint)
void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint)
void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint)

override fun draw(canvas: Canvas) {
super.draw(canvas)
mPaint.strokeWidth = 10f
mPaint.setColor(Color.RED)
//1.
canvas.drawLine(100f,100f,600f,600f,mPaint)
//2.
canvas.drawLines(floatArrayOf(
100f,100f,600f,600f
),mPaint)
//3. //第一个参数是一个坐标点组
//第二个参数从哪个坐标点开始
//第三个参数坐标点是取出 4 个数据
canvas.drawLines(floatArrayOf(
100f,100f,600f,600f
),0,4,mPaint)
}

效果都一样

绘制点

//x,y 点坐标
void drawPoint(float x, float y, @NonNull Paint paint)
//pts 坐标组,offset 从哪个点开始,count:取多少个点
void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
@NonNull Paint paint)
//pts 坐标组
void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint)

//1
canvas.drawPoint(100f, 100f, mPaint)

//2.
var offset = 0
var pts = floatArrayOf(
500f + offset, 100f, 500f + offset, 200f,
500f + offset, 300f, 500f + offset, 600f,
500f + offset, 700f, 500f + offset, 800f,
500f + offset, 900f, 500f + offset, 1000f
)
mPaint.setColor(Color.BLUE)
canvas.drawPoints(pts, 0, 16, mPaint)

//3.
mPaint.setColor(Color.GREEN)
offset = 100
pts = floatArrayOf(
500f + offset, 100f, 500f + offset, 200f,
500f + offset, 300f, 500f + offset, 600f,
500f + offset, 700f, 500f + offset, 800f,
500f + offset, 900f, 500f + offset, 1000f
)
canvas.drawPoints(pts, mPaint)
复制代码

效果如下:

绘制矩形

RectF :保存 float 矩形结构

Rect:保存 int 矩形结构

这里会用到 View 坐标点的知识,对 left,top,right,bottom 还不熟悉的可以参考 高级 UI 成长之路 (一) View 的基础知识你必须知道

//1.
void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
super.drawRect(rect, paint);
//2.
void drawRect(@NonNull Rect r, @NonNull Paint paint)
//3.
void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)

//1.
var rect = RectF(100.50f,100.50f,500.50f,500.50f)
mPaint.style = Paint.Style.FILL
canvas.drawRect(rect,mPaint)

//2.

var rect2 = Rect(300,300,600,600)
mPaint.style = Paint.Style.FILL
mPaint.setColor(Color.BLUE)
mPaint.alpha = 100
canvas.drawRect(rect2,mPaint)

//3.
mPaint.style = Paint.Style.FILL
mPaint.setColor(Color.YELLOW)
canvas.drawRect(500f,500f,1000f,1000f,mPaint)

效果如下:

绘制路径

//根据 path 绘制路径
void drawPath(@NonNull Path path, @NonNull Paint paint)

/**

  • 1. 绘制路径线
    */
    var path = Path()
    //1. 设置起始点
    path.moveTo(100f, 100f)
    //2. 第二条线的起点就是moveTo 设置的启动
    path.lineTo(100f,300f)
    //3. 第三条线的起点就是第二条的终点,依次类推
    path.lineTo(300f,500f)
    path.lineTo(500f,200f)
    //4. 闭合
    path.close()
    canvas.drawPath(path, mPaint)

/**

  • 2. 绘制弧度路径
    */
    var path2 = Path()
    //绘制弧度的起始位置
    path2.moveTo(100f,600f)
    var rectF = RectF(100f,600f,600f,1000f)
    //第一个参数生成椭圆的矩形,第二个参数是弧开始的角度以 X 轴正方向为 0 度,第三个参数是弧持续的角度
    path2.arcTo(rectF,0f,90f)
    canvas.drawPath(path2, mPaint)

上面注释很详细,就不在解释了

绘制圆/椭圆

//绘制椭圆
void drawOval(@NonNull RectF oval, @NonNull Paint paint)
//绘制圆
void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

/**

  • 1. 绘制椭圆
    */
    canvas.drawOval(RectF(100f,500f,600f,800f),mPaint)

/**

  • 2. 绘制圆
    */
    mPaint.setColor(Color.YELLOW)
    mPaint.alpha = 100
    canvas.drawCircle(400f,400f,200f,mPaint)
绘制 Bitmap

//
val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.gild_3)
//第二个,第三个参数代表起点位置
canvas.drawBitmap(bitmap,100f,100f,mPaint)

绘制 Text

//1.
void drawText(@NonNull char[] text, int index, int count, float x, float y,
@NonNull Paint paint)
//2.
void drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
//3.
void drawText(@NonNull String text, int start, int end, float x, float y,
@NonNull Paint paint)
//4.
void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
@NonNull Paint paint)

/**

  • 取 0 ~ 5 位置的 text 进行绘制
    */
    mPaint.textSize = 100f
    canvas.drawText(charArrayOf(‘1’,‘2’,‘3’,‘4’,‘5’),0,5,200f,200f,mPaint)

/**

*/
canvas.drawText(“12345”,300f,300f,mPaint)

/**

  • 3.取 0 ~ 5 位置的 text 进行绘制
    */
    canvas.drawText(“12345”,0,5,400f,400f,mPaint)
根据路径绘制 Text

//从 hOffset 向外偏移 vOffset px 来绘制 text
void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
float vOffset, @NonNull Paint paint)
复制代码

mPaint.setColor(Color.GREEN)
mPaint.alpha = 100

mPaint.textSize = 100f
var path = Path()
//1. 设置起始点
path.moveTo(300f, 300f)
//2. 第二条线的起点就是moveTo 设置的启动
path.lineTo(300f,500f)
//3. 第三条线的起点就是第二条的终点,依次类推
path.lineTo(500f,800f)
path.lineTo(800f,200f)
//4. 闭合
path.close()
canvas.drawPath(path,mPaint)
//从0偏移100px的像素
canvas.drawTextOnPath(“12345asodnaspdnfpoashfeuinfapjn”,path,0f,100f,mPaint)

绘制 弧/扇形

//1.
void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint)
//2.
void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint)

var rectF = RectF(100f, 100f, 500f, 500f)
/**

  • 1. 绘制弧
  • @param ovar : 矩形坐标
  • @param startAngle : 开始的角度
  • @param sweepAngle : 结束的角度
  • @param userCenter : 如果为true,则将椭圆的中心包括在圆弧中
  • @param paint : 画笔
    */
    canvas.drawArc(rectF, 0f, 90f, true, mPaint)

/**

  • 2. 绘制弧
    */
    canvas.drawArc(100f,500f,500f,900f,0f,90f,false,mPaint)
绘制圆角矩形

//1.
void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
//2.
void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Paint paint)

/**

  • 1. 根据 RectF 绘制圆角矩形
  • @param rx: x 轴上的圆角半径
  • @param ry: y 轴上的圆角半径
    /
    canvas.drawRoundRect(rectF,50f,50f,mPaint)
    /
    *
  • 2. 根据输入矩形位置绘制圆角矩形
    */
    canvas.drawRoundRect(100f,600f,500f,900f,100f,100f,mPaint)
Canvas 变换
translate - 图层平移

//dx/dy:x/y 点新位置
void translate(float dx, float dy)

scale- 图层缩小 0~1

//x,y 缩小系数 0~1 之间 越大说明越接近原始图像
void scale(float sx, float sy)
复制代码

/**

  • 1. 原始矩形
    */
    mPaint.color = Color.RED
    mPaint.alpha = 100
    canvas.drawRoundRect(rectF,50f,50f,mPaint)

/**

  • 2.将原始图形缩小 0.5 倍
    */
    var rectF2 = RectF(100f, 100f, 500f, 500f)
    mPaint.color = Color.BLUE
    mPaint.alpha = 100
    canvas.scale(0.5f,0.5f)
    canvas.drawRoundRect(rectF2,50f,50f,mPaint)
rotate - 图层旋转

//1.
void rotate(float degrees)
//2.
void rotate(float degrees, float px, float py)

/**

  • 1. 原始矩形
    */
    mPaint.color = Color.RED
    mPaint.alpha = 100
    canvas.drawRoundRect(rectF,50f,50f,mPaint)

/**

  • 2.将原始图形旋转 45°
    */
    mPaint.color = Color.BLUE
    mPaint.alpha = 100
    canvas.rotate(45f)
    canvas.drawRoundRect(rectF,50f,50f,mPaint)

/**

  • 3.将原始图形旋转 280°
  • 以 坐标点 500,100 顺时针旋转 280°
    */
    mPaint.color = Color.YELLOW
    mPaint.alpha = 100
    canvas.rotate(280f,500f,100f)
    canvas.drawRoundRect(rectF,50f,50f,mPaint)
skew - 图层错切

//错切是在某方向上,按照一定的比例对图形的每个点到某条平行于该方向的直线的有向距离做放缩得到的平面图形。水平错切(或平行于X轴的错切)是一个将任一点(x,y)映射到点(x+my,y)的操作,m是固定参数,称为错切因子
//sx和sy分就是错切因子,为倾斜角度tan值,这里倾斜45度值为1
void skew (float sx, float sy)

/**

  • 1. 原始图形
    /
    mPaint.color = Color.RED
    mPaint.alpha = 100
    canvas.drawRoundRect(rectF,50f,50f,mPaint)
    /
    *
  • 2.图层开始错切
    */
    canvas.skew(0f,0.5f)
    mPaint.color = Color.BLUE
    mPaint.alpha = 100
    canvas.drawRoundRect(rectF,50f,50f,mPaint)
Matrix

api详细使用

/**

  • 原始图形
    /
    canvas.drawBitmap(mBitmap,100f,100f,mPaint)
    /
    *
    *1. 矩阵平移 500,500
    */
    var matrix = Matrix()
    matrix.setTranslate(500f,500f)
    canvas.drawBitmap(mBitmap,matrix,mPaint)

/**

  • 2. 矩阵缩放 0.5 倍
    */
    var matrix2 = Matrix()
    matrix2.setScale(0.5f,0.5f)
    canvas.drawBitmap(mBitmap,matrix2,mPaint)

/**

  • 3. 矩阵旋转 125°
    */
    var matrix3 = Matrix()
    matrix3.setRotate(125f,500f,500f)
    canvas.drawBitmap(mBitmap,matrix3,mPaint)

/**

  • 4. 错切
    */
    var matrix4 = Matrix()
    matrix4.setSkew(0.5f,0.5f)
    canvas.drawBitmap(mBitmap,matrix4,mPaint)
裁剪画布

//裁剪
boolean clipRect(RectF rect, Region.Op op);
boolean clipRect(Rect rect, Region.Op op);
boolean clipRect(RectF rect);
boolean clipRect(Rect rect);
boolean clipRect(float left, float top, float right, float bottom, Region.Op op);
boolean clipRect(float left, float top, float right, float bottom);
boolean clipRect(int left, int top, int right, int bottom);
boolean clipPath(Path path, Region.Op op);
boolean clipPath(Path path);
boolean clipRegion(Region region, Region.Op op);
boolean clipRegion(Region region);

上图中的 1 代表原始的图层,未被裁剪;2 代表已经裁剪了的图层;3,不管怎么绘制只能在该区域内部绘制。

/**

  • 1. 原始图形
    /
    mPaint.color = Color.RED
    mPaint.alpha = 100
    canvas.drawRect(300f,300f,700f,700f,mPaint)
    canvas.drawText(“1.原始”,400f,600f,Paint(Paint.ANTI_ALIAS_FLAG).also {
    it.textSize = 100f
    it.color = Color.WHITE
    })
    /
    *
  • 2. 在 RectF 矩形区域裁剪一块画布,绘制图形只能在该区域中绘制
    */
    var rectf2 = RectF(100f, 100f , 500f, 500f);
    canvas.clipRect(rectf2)
    mPaint.color = Color.BLUE
    mPaint.alpha = 100
    canvas.drawColor(mPaint.color)
    canvas.drawText(“2.clip”,200f,200f,Paint(Paint.ANTI_ALIAS_FLAG).also {
    it.textSize = 100f
    it.color = Color.WHITE
    })

/**

  • 3. 在 300,300;700,700 坐标点上绘制矩形
    */
    mPaint.color = Color.YELLOW
    mPaint.alpha = 100
    canvas.drawRect(300f,300f,700f,700f,mPaint)
    canvas.drawText(“3.裁剪之后”,350f,400f,Paint(Paint.ANTI_ALIAS_FLAG).also {
    it.textSize = 30f
    it.color = Color.WHITE
    })
画布的保存与恢复

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

as.drawText(“3.裁剪之后”,350f,400f,Paint(Paint.ANTI_ALIAS_FLAG).also {
it.textSize = 30f
it.color = Color.WHITE
})

画布的保存与恢复

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-KFONTDI8-1713698993362)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值