这可能是第二好的自定义 View 教程之绘制,2024年最新android地图开发

一切的开始:onDraw()

自定义绘制的上手非常容易:提前创建好 Paint 对象,重写 onDraw(),把绘制代码写在 onDraw() 里面,就是自定义绘制最基本的实现。大概就像这样:

Paint paint = new Paint();

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

// 绘制一个圆
canvas.drawCircle(300, 300, 200, paint);
}

就这么简单。所以关于 onDraw() 其实没什么好说的,一个很普通的方法重写,唯一需要注意的是别漏写了 super.onDraw()。你可能会点击进去查看到 super.onDraw() 其实是一个空实现,那可能只是因为你继承的是 View 吧,你继承 View 的其它子类试试?

Canvas.drawXXX() 系列方法的使用

Canvas 下面的 drawXXX() 系列的方法真没啥好讲的,你想画什么图形直接画就好了。而参数其实也给的非常的明了。你一定要全部了解学习的话,直接可以去看官方文档或者凯哥的 自定义View 1-1

  • 填充颜色:Canvas.drawColor(@ColorInt int color)
  • 画圆:drawCircle(float centerX, float centerY, float radius, Paint paint)
  • 画矩形:drawRect(float left, float top, float right, float bottom, Paint paint)
  • 画点:drawPoint(float x, float y, Paint paint)
  • 批量画点:drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint)
  • 画椭圆:drawOval(float left, float top, float right, float bottom, Paint paint)
  • 画线:drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
  • 画弧线或者扇形:drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
  • 画自定义图形:drawPath(Path path, Paint paint)
  • 画 Bitmap:drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
  • 画文字:drawText(String text, float x, float y, Paint paint)

其中可以看到有不少的坐标值参数,你只需要明白的一点是,在 Android 的绘制中,坐标系是这样的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自扔物线

值得注意的是:

  • 在画弧线或者扇形中的角度 angle,x 轴正方向为 0°,顺时针方向为正角度,逆时针为负角度。
  • 画弧线或者扇形中的 sweepAngle 参数,代表的是绘制的角度,不要被其它方法误导成了以为是绘制结束时候的角度,官方为何在这里做了个变换,其实我也不知道。
  • drawPath() 方法可能相对其它较难,但却是自定义 View 实际应用中最多的。非常需要了解其三类方法。这里直接摘抄凯哥的 自定义 View 1-1
  • drawBitmap() 方法中有个参数是 Bitmap,友情提示:Bitmap 可以通过 BitmapFactory.decodeXXX() 获得。

Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形。Path 可以归结为两类方法:

  • 直接描述路径,也可以分为两组:
    • 添加子图形:addXXX(), 此类方法在特定情况下几个 Canvas.drawPath() 等同于 Canvas.drawXXX()
    • 画直线或曲线:xxxTo(): 这一组和第一组 addXxx() 方法的区别在于,第一组是添加的完整封闭图形(除了 addPath() ),而这一组添加的只是一条线。
  • 辅助设置或计算,因为应用场景很少,凯哥也只讲了其中一个方法: Path.setFillType(Path.FillType ft) 设置填充方式

上面有比较多的提到 Paint 这个参数,实际上它是真的很好用,直接在下面讲解。

Paint 的使用

Paint 真的很重要,在自定义绘制中充当关键角色:画笔,所以我们自然可以为「画笔」做很多操作,比如设置颜色、绘制模式、粗细等。

  • Paint.setStyle(Style style) 设置绘制模式
  • Paint.setColor(int color) 设置颜色
  • Paint.setStrokeWidth(float width) 设置线条宽度
  • Paint.setTextSize(float textSize) 设置文字大小
  • Paint.setAntiAlias(boolean aa) 设置抗锯齿开关

嗯,对,抗锯齿开关还可以直接在 Paint 初始化的时候直接作为构造参数:Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG)

Paint 的 API 大致可以分为 4 类:

  • 颜色
  • 效果
  • drawText() 相关
  • 初始化

凯哥专门拿了一期对 Paint 做了重点讲解,依然在实际场景应该用处不大,所以需要的直接点击 这里 跳转。

如果你想先知道凯哥都讲了什么,我这里也单独给你总结一下:

首先是给 Paint 设置着色器。
  • Paint.setShader(Shader shader):设置着色器,实际上我们一般传递的参数不会直接传递 Shader,而会选择直接传递它的子类,具体效果下面给出。
    • 线性渐变:LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,TileMode tile)

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      图片来自扔物线

     int centerColor, int edgeColor, @NonNull TileMode tileMode)
    ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fuser-gold-cdn.xitu.io%2F2017%2F11%2F8%2F7b98fe75bd81f86fe01802dd04148878%3FimageView2%2F0%2Fw%2F1280%2Fh%2F960%2Fignore-error%2F1&pos_id=img-NSI4XOYT-1712765080513)
    
    图片来自扔物线
    
*   扫描渐变:SweepGradient(float cx, float cy, int color0, int color1)  
    
    ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fuser-gold-cdn.xitu.io%2F2017%2F11%2F8%2F0e71db67673ebc8d68ddd2f48fb5f116%3FimageView2%2F0%2Fw%2F1280%2Fh%2F960%2Fignore-error%2F1&pos_id=img-IGZO1GH5-1712765080514)
    
    图片来自扔物线
    
      
    还有很多,就不一一给图了。
*   BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)
*   混合着色:ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)

其中需要注意的是:

  • Paint.setShader() 优先级高于 Paint.setColor() 系列方法。
  • 最后一个 tile 参数,代表的是断点范围之外的着色规则。它是一个枚举类型,有三种参数。
  • CLAMP : 直译是「夹子模式」,会在端点之外延续端点处的颜色。
  • MIRROR : 镜像模式。
  • REPEAT : 重复模式。
其次是设置颜色过滤

设置颜色过滤可以采用 Paint.setColorFilter(ColorFilter colorFilter) 方法。它的名字已经足够解释它的作用:为绘制设置颜色过滤。颜色过滤的意思,就是为绘制的内容设置一个统一的过滤策略,然后 Canvas.drawXXX() 方法会对每个像素都进行过滤后再绘制出来。

这个其实貌似在拍照或者照片整理类应用上用的比较多,其它方面貌似我还很少遇到过,GitHub 上的库 StyleImageView 诠释的很棒。

再其它也就没啥好说的,感兴趣直接去看 HenCoder

这里可以重点说一下:Paint.setStrokeCap(Paint.Cap cap),设置线头的形状。线头形状有三种:BUTT 平头、ROUND 圆头、SQUARE 方头。默认为 BUTT

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自扔物线

虚线是额外加的,虚线左边是线的实际长度,虚线右边是线头。有了虚线作为辅助,可以清楚地看出 BUTT 和 SQUARE 的区别。

Canvas 的文字绘制

Canvas 的文字绘制方法有三个:

  • drawText()
  • drawTextRun()
  • drawTextOnPath()

我们大多数情况用不了那么多,所以同样这里不做详解,对于始终想追根到底的同学,同样给你提供了 凯哥的链接

下面只对部分需要注意的重点总结一下。

drawText()
  • drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
    其中的参数很简单:text 是文字内容,x 和 y 是文字的坐标。但需要注意:这个坐标并不是文字的左上角,而是一个与左下角比较接近的位置。大概在这里:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图片来自扔物线

    而如果你像绘制其他内容一样,在绘制文字的时候把坐标填成 (0, 0),文字并不会显示在 View 的左上角,而是会几乎完全显示在 View 的上方,到了 View 外部看不到的位置:
    canvas.drawText(text, 0, 0, paint);
    大概是这样:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图片来自扔物线

另外,Canvas.drawText() 只能绘制单行的文字,而不能换行。就算显示不完,也会直接绘制到屏幕外面去。

那如果要换行,得 drawText() 很多次吗?并没有,还有一个 StaticLayout 可以完美达到我们的效果。对于详细使用,这里也不多提了。

drawTextRun()drawTextOnPath(),运用的可能并不多,这里就不说了。

简单提一下设置效果辅助类吧,这个可能直接就有用。

Paint 对文字绘制的辅助
  • 设置文字大小:Paint.setTextSize(float textSize)
  • 设置字体:Paint.setTypeface(Typeface typeface),其中的 Typeface 里面涵盖了相关字体。另外,还可以通过 Typeface.createFromAsset(AssetManager mgr, String path) 来设置自定义字体,其中 mgr 可以给 getResources().getAssets()path 给文件名字,需要把字体文件 .ttf 放在工程的 res/assets 下,「assets」是新建的专用目录。
  • 设置文字是否加粗:Paint.setFakeBoldText(boolean fakeBoldText)
  • 设置文字是否加删除线:Paint.setStrikeThruText(boolean strikeThruText)
  • 设置文字是否加下划线:Paint.setUnderlineText(boolean underlineText)
  • 设置字体倾斜度:Paint.setTextSkewX(float skewX) 「skewX」 向左倾斜为正。
  • 设置文字横向放缩:Paint.setTextScaleX(float scaleX)
  • 设置字体间距,默认值为 0:Paint.setLetterSpacing(float letterSpacing) 这个不是行间距哦。
  • 设置文字对齐方式:Paint.setTextAlign(Paint.Align align),其中「align」有三个值:LEFTCENTERRIGHT,默认值是 LEFT
  • 设置绘制所使用的 Locale:Paint.setTextLocale(Locale locale) / Paint.setTextLocales(LocaleList locales)

实际上,这些方法基本都在我们 TextView 里面的。

自定义 View 之范围裁切

范围裁切主要采用两个方法:

  • clipRect()
  • clipPath()

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

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

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

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

新的开始

改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。

《系列学习视频》

《系列学习文档》

《我的大厂面试之旅》

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

《我的大厂面试之旅》

[外链图片转存中…(img-Na6Y2aSC-1712765080519)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-5oG79MWB-1712765080519)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值