🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 1. 前言 Shape类可以用来实现不同的图像效果,Shape是一个抽象类,所以在使用的时候需要使用其子类,有: ![](https://img.kancloud.cn/41/d6/41d6c02e9207fbadf587f8b83752e558_1100x510.png) ## 1.1 RectShape 通过ShapeDrawable(Shape shape)传入一个RectShape,然后就可以得到一个矩形,最后在onDraw函数中传入画布对象,绘制该矩形 。比如下面的案例: ~~~ class RectShapeDemo: View { constructor(context: Context?) : super(context) {init()} constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){init()} constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( context, attrs, defStyleAttr ){init()} private lateinit var mShapeDrawable: ShapeDrawable private fun init(){ // 关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null) // 实例化RectShape val rectShape = RectShape() // Creates a ShapeDrawable with a specified Shape. mShapeDrawable = ShapeDrawable(rectShape) // 指定当前 ShapeDrawable 在当前控件中的显示位置 mShapeDrawable.bounds = Rect(50, 50, 500, 500) // 设置绘制mShapeDrawable中的画笔颜色 mShapeDrawable.paint.color = Color.RED } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) // 将是将 ShapeDrawable绘制在当前画布上 canvas?.apply { mShapeDrawable.draw(this) } } } ~~~ 效果: ![](https://img.kancloud.cn/99/ba/99bad9b1debba322655c71992098802d_151x147.png) ## 1.2 OvalShape 这里可以指定bounds来创建一个椭圆或者圆形的Shape,使用和上一个案例一直,唯一的区别在于init方法: ~~~ private fun init(){ // 关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null) // 实例化OvalShape val ovalShape = OvalShape() // Creates a ShapeDrawable with a specified Shape. mShapeDrawable = ShapeDrawable(ovalShape) // 设置要绘制的这个Drawable mShapeDrawable.bounds = Rect(50, 50, 500, 500) // 设置绘制mShapeDrawable中的画笔颜色 mShapeDrawable.paint.color = Color.RED } ~~~ 结果: ![](https://img.kancloud.cn/0e/2a/0e2a0f97288b7ed95020f8046d6e75eb_156x147.png) ## 1.3 ArcShape 在 OvalShape 所形成的椭圆的基础上,将其进行角度切割所形成的扇形。也就是绘制得到一个扇形的图像。其 中扇形开始的 0°在椭圆的 X 轴正方向上。在初始化ArcShape的时候,就可以直接指定其实角度和扫过的角度。比如下面的案例: ~~~ private fun init(){ // 关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null) // 实例化OvalShape val arcShape = ArcShape(0f, 90f) // Creates a ShapeDrawable with a specified Shape. mShapeDrawable = ShapeDrawable(arcShape) // 设置要绘制的这个Drawable mShapeDrawable.bounds = Rect(50, 50, 500, 500) // 设置绘制mShapeDrawable中的画笔颜色 mShapeDrawable.paint.color = Color.RED } ~~~ 同样的,也还是只修改了init方法,也就是实例化了ArcShape对象。结果: ![](https://img.kancloud.cn/d3/b4/d3b45b1437e75b6379e5aee1042756c8_191x144.png) ## 1.4 RoundRectShape 指圆角矩形。其实,它不仅能实现圆角矩形,它的本意是实现镂空的圆角矩形。其构造函数: ~~~ RoundRectShape(@Nullable float[] outerRadii, @Nullable RectF inset, @Nullable float[] innerRadii) ~~~ * outerRadii:外围矩形的各个角的角度大小,需要填充 8 个数字,每两个数字一 组,分别对应(左上角、右上角、右下角、左下角)4 个角的角度。每两个一组的数 字构成一个椭圆,第一个数字代表椭圆的 X 轴半径,第二个数字代表椭圆的 Y 轴半径。 * inset:表示内部矩形与外部矩形各边的边距。RectF 的 4 个值分别对应 left、top、 right、bottom 4 条边的边距。如果不需要内部矩形的镂空效果,则可以传入 null。 * float\[\] innerRadii:表示内部矩形的各个角的角度大小,同样需要填充 8 个数字,其含 义与 outerRadii 一样。如果不需要指定内部矩形的各个角的角度,则可以传入 null。 至于上面提到的8个点的数组,简略图示为: ![](https://img.kancloud.cn/32/25/32251285c207f53be1d4bb8fec82a00b_1369x421.png) 比如下面的案例: ~~~ private fun init(){ // 关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null) // 外围矩形的各个角的角度大小 val outerRadii = floatArrayOf(15f, 15f, 0f, 0f, 15f, 15f, 0f, 0f) // 表示内部矩形与外部矩形各边的边距。 val inset = RectF(10f, 8f, 10f, 8f) // 内部矩形各个角的角度大小 val innerRadii = floatArrayOf(80f, 20f, 0f, 0f, 20f, 80f, 0f, 0f) // 创建RoundRectShape val roundRectShape = RoundRectShape(outerRadii, inset, innerRadii) // Creates a ShapeDrawable with a specified Shape. mShapeDrawable = ShapeDrawable(roundRectShape) // 设置要绘制的这个Drawable mShapeDrawable.bounds = Rect(50, 50, 300, 200) // 设置绘制mShapeDrawable中的画笔颜色 mShapeDrawable.paint.color = Color.RED } ~~~ 效果: ![](https://img.kancloud.cn/f7/62/f76204c049d16ba57cb9f51df1abf0d4_382x225.png) ## 1.5 PathShape 也就是构造一个可根据路径绘制的 Shape。比如下面的案例: ~~~ private fun init(){ // 关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null) val path = Path() path.moveTo(400f/6, 400f) path.lineTo(200f, 0f) path.lineTo(400f * 5/6, 400f) path.lineTo(0f, 150f) path.lineTo(400f, 150f) path.lineTo(400f/6, 400f) // 封闭前面点所绘制的路径 path.close() val pathShape = PathShape(path, 400f, 400f) // Creates a ShapeDrawable with a specified Shape. mShapeDrawable = ShapeDrawable(pathShape) // 设置要绘制的这个Drawable mShapeDrawable.bounds = Rect(50, 50, 500, 500) // 设置绘制mShapeDrawable中的画笔颜色 mShapeDrawable.paint.color = Color.RED } ~~~ 结果: ![](https://img.kancloud.cn/4d/6d/4d6db9cfb1f4a34a3145c830e7a7547f_189x147.png)