建立自己的王国:Android 自定义封装View-6
2023-02-27 本文已影响0人
努尔江
前言:
开发中很多人需要Shape资源,圆角大小,描边颜色,描边厚度等等。但是每次为了一个差异创建xml资源文件是很浪费资源的事情。所以这次的亮点是一个圆角,描边等属性的自定义View。
国际惯例-一些能实现的效果
实现思路:
可以说是通过2种不同的图案的结合体。描边+内部颜色。
如果是圆角可以通过canvas.drawRoundRect()
来画出圆角,但是如果每个圆角都不一样,就不能用这个方法来。
通过查询发现,canvas.drawPath()
, 在path
的方法里path.addRoundRect()
来可以把圆角参数加进去。
//为了4个角的角度值。
val corners = floatArrayOf(
80,80, //左上角
80,80,//右上角
0,0, //左下角
0,0 //右下角
)
//添加
mPath.addRoundRect(mRectF, corners, Path.Direction.CW)
//画出来
canvas!!.drawPath(mPath, mPaint)
为了考虑到View
性能, 背景色从描边内画出。(也可以先画背景,再画描边)
实现:
1.需要定义的一些自定义属性
<!-- 全部角半径-->
<attr name="sv_cornersRadius" format="dimension"/>
<!-- 左上角半径-->
<attr name="sv_cornerTopLeft" format="dimension"/>
<!-- 右上角 半径-->
<attr name="sv_cornerTopRight" format="dimension"/>
<!-- 左下角半径-->
<attr name="sv_cornerBottomLeft" format="dimension"/>
<!-- 右下角半径-->
<attr name="sv_cornerBottomRight" format="dimension"/>
<!-- 描边颜色-->
<attr name="sv_strokeColor" format="color" />
<!-- 描边厚度-->
<attr name="sv_strokeWidth" format="dimension"/>
<!-- 背景色-->
<attr name="sv_soldColor" format="color"/>
自定义属性需要注意的是,如果设置了全角圆半径值,那么下面的四个参数就没有意义了。换句话说:全圆角半径和分别设置的值是互斥的。设置全角值,快,但是会有4个边角不一样的情况。如果都同时设置了,需要处理。为了这个问题,我的思路是先用全角值赋值给四个边角,然后用属性中把四个边角值再赋值。
//如果当前的值为空,那么用总圆角值。如果不空 用这个值。
private fun provideWithCare(cornerRadius: Float): Float {
if (cornerRadius== 0f) return cornersRadius
return cornerRadius
}
这样下来就是,4个边角值和全圆角值可以同时使用。互不影响。
其他代码如下:
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
//为了4个角的角度值。
val corners = floatArrayOf(
provideWithCare(cornerTopLeft), provideWithCare(cornerTopLeft),
provideWithCare(cornerTopRight), provideWithCare(cornerTopRight),
provideWithCare(cornerBottomRight), provideWithCare(cornerBottomRight),
provideWithCare(cornerBottomLeft), provideWithCare(cornerBottomLeft)
)
//底色(背景色)
//style 是线风格。
mPaint.style = Paint.Style.FILL
mPaint.color = soldColor
mPaint.strokeWidth = 1f
mRectF.left = strokeWidth / 2f
mRectF.top = strokeWidth / 2f
mRectF.right = width - strokeWidth / 2f
mRectF.bottom = height - strokeWidth / 2f
mPath.addRoundRect(mRectF, corners, Path.Direction.CW)
canvas!!.drawPath(mPath, mPaint)
//如果为0,不需要绘制边
if (strokeWidth != 0f) {
//切换style属性实心。
mPaint.style = Paint.Style.STROKE
mPaint.strokeWidth = strokeWidth
mPaint.color = strokeColor
mRectF.left = strokeWidth / 2f
mRectF.top = strokeWidth / 2f
mRectF.right = width - strokeWidth / 2f
mRectF.bottom = height - strokeWidth / 2f
mPath.addRoundRect(mRectF, corners, Path.Direction.CW)
canvas.drawPath(mPath, mPaint)
}
}
//初始化 一级获取属性值。
private fun initView(context: Context?, attrs: AttributeSet?) {
val ta = context!!.obtainStyledAttributes(attrs, R.styleable.ShapeableView)
//全部边框值
cornersRadius = ta.getDimension(R.styleable.ShapeableView_sv_cornersRadius, 0f)
//边框-边角
cornerTopLeft = ta.getDimension(R.styleable.ShapeableView_sv_cornerTopLeft, 0F)
cornerTopRight = ta.getDimension(R.styleable.ShapeableView_sv_cornerTopRight, 0F)
cornerBottomLeft = ta.getDimension(R.styleable.ShapeableView_sv_cornerBottomLeft, 0F)
cornerBottomRight = ta.getDimension(R.styleable.ShapeableView_sv_cornerBottomRight, 0F)
//边框颜色
strokeColor = ta.getColor(R.styleable.ShapeableView_sv_strokeColor, Color.BLUE)
strokeWidth = ta.getDimension(R.styleable.ShapeableView_sv_strokeWidth, 0f)
//背景颜色
soldColor = ta.getColor(R.styleable.ShapeableView_sv_soldColor, Color.CYAN)
ta.recycle()
}
就这些。如果想用这个类,可以介入我的jitpack库:
build.gradle 内请添加。
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
依赖
dependencies {
implementation 'com.github.neo-turak:ktx:1.0.8
}
使用方法:
<com.github.neoturak.view.ShapeableView
android:layout_marginTop="10dp"
android:layout_width="100dp"
android:layout_height="40dp"
app:sv_soldColor="#cc0000"
app:sv_strokeColor="#000000"
app:sv_strokeWidth="2dp"
app:sv_cornersRadius="8dp"
/>
谢谢欣赏🙏。