建立自己的王国: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"
        />

谢谢欣赏🙏。

上一篇 下一篇

猜你喜欢

热点阅读