Android custom View related summary

Inherit View and override onDraw method

Usually used to achieve complex and irregular effects, you need to support wrap_content and padding yourself. Kotlin code for custom circular progress bar component

class MyCircleProgress : View {
    
    
    private var mWidth = 0
    private var mHeight = 0
    private var progress = 0.6

    constructor(context: Context) : super(context) {
    
    

    }

    constructor(context: Context, attr: AttributeSet) : super(context, attr) {
    
    

    }

    private fun dp2px(dp: Int): Int {
    
    
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), Resources.getSystem().displayMetrics).toInt()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        when(widthMode) {
    
    
        	// 处理match_parent和固定宽度的情况
            MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY -> mWidth = widthSize
            // 处理wrap_content
            MeasureSpec.AT_MOST -> mWidth = dp2px(200)
        }
        when(heightMode) {
    
    
            MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY -> mHeight = heightSize
            MeasureSpec.AT_MOST -> mHeight = dp2px(200)
        }
        setMeasuredDimension(mWidth, mHeight)
    }

    override fun onDraw(canvas: Canvas?) {
    
    
        canvas?.apply {
    
    
            val paint  = Paint().apply {
    
    
            	// Paint设置的颜色默认是有透明度的,且透明度为0
            	// 并且在kotlin中0xff00ffff超过了int的范围,所以这里要调用toInt()
                color = 0xff00ffff.toInt()
                isAntiAlias = true
                this.strokeWidth = 10F
                style = Paint.Style.STROKE
            }
            // 设置圆弧的绘制区域,处理padding
            val rectF = RectF(10F + paddingLeft, 10F + paddingTop,
                (mWidth - 10 - paddingRight).toFloat(), (mHeight - 10 - paddingBottom).toFloat())
            // 绘制圆弧,表示进度
            drawArc(rectF, -90F, (360 * progress).toFloat(), false, paint)
            paint.color = 0xff000000.toInt()
            paint.style = Paint.Style.FILL
            paint.textSize = 50F
            // 绘制文字,显示进度百分比
            drawText("${
      
      (100 * progress).toInt()} %", (mWidth / 2).toFloat(), (mHeight / 2).toFloat(), paint)
        }
    }

}

Inherit a specific View to override the onDraw method

Used to extend some existing View functions, such as TextView, AppCompatImageView, without supporting wrap_content and padding. Kotlin code for custom circular ImageView

class MyImageView : androidx.appcompat.widget.AppCompatImageView {
    
    

    constructor(context: Context) : super(context) {
    
    

    }

    constructor(context: Context, attr: AttributeSet) : super(context, attr) {
    
    

    }

    override fun onDraw(canvas: Canvas?) {
    
    
        val paint = Paint().apply {
    
    
            color = 0xffffffff.toInt()
            isAntiAlias = true
        }
        val xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)

        canvas?.apply {
    
    
            saveLayer(0F, 0F, width.toFloat(), height.toFloat(), null, Canvas.ALL_SAVE_FLAG)
            // 直接使用clipPath会有锯齿问题
            // canvas.clipPath(path)
            canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), (width / 2 - 1).toFloat(), paint)
            val bitmap = drawable.toBitmap()
            val bitmapRect = Rect(0, 0, bitmap.width, bitmap.height)
            val canvasRect = Rect(0, 0, width, height)
            paint.xfermode = xfermode

            drawBitmap(bitmap, bitmapRect, canvasRect, paint)
            restore()
        }
    }
}

final effect

In addition to the above two methods, we can also inherit ViewGroup and specific ViewGroup (such as FrameLayout) to implement custom View. In actual development, it is often necessary to achieve the effect of combining several Views together, which can be achieved by inheriting a specific ViewGroup (generally not directly inheriting ViewGroup, unless necessary)

Guess you like

Origin blog.csdn.net/a16302010048/article/details/108739663