【一看就懂】自定义View入门实践,实现外方内圆效果

Abina ·
更新时间:2024-11-10
· 962 次阅读

本文作为自定义View的初步实践,取材自《android开发艺术探索》

目录效果如下方法activity_main.xmlattr.xml属性CircleView重写onDraw()重写onMeasure()java源代码 效果如下

在这里插入图片描述

方法 activity_main.xml

这是我们自己设计的CircleView控件,其在xml中如下表示

其中

xmlns:app="http://schemas.android.com/apk/res-auto"

表示自定义属性,使得我们可以在CircleView中使用

app:circle_color="#FFFF00"

那circle哪来的呢?这里我们要为CircleView构建属于自己的attr.xml属性

attr.xml属性

在values新建attr.xml
写上

其中资源为styleable ,和id,layout同级,名字为CircleView,这里我们定义的属性名为circle_color,属性是color,当然也可以定义其他format

CircleView

接下来再在新建的CircleView类中取到color,在构造方法中

public CircleView(Context context, AttributeSet attributeSet) { super(context,attributeSet); TypedArray a = context.obtainStyledAttributes(attributeSet,R.styleable.CircleView); mColor = a.getColor(R.styleable.CircleView_circle_color, Color.RED); a.recycle(); Log.d(TAG, "CircleView: Second"); init(); } private void init() { mPaint.setColor(mColor); }

用TypedAtrray获取,如图
在这里插入图片描述

重写onDraw()

然后我们再将已经获取颜色的Paint用canvas画出圆形,重写onDraw方法

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingLeft(); int paddingTop = getPaddingLeft(); int paddingBottom = getPaddingLeft(); int width = getWidth() - paddingLeft - paddingRight; //缩减宽高 int height = getHeight() - paddingTop - paddingBottom; int radius = Math.min(width,height)/2; canvas.drawCircle(width/2+paddingLeft,height/2+paddingBottom,radius,mPaint); }

这里我们画了很大的精力取计算Padding,因为我们在activity_main中设置了padding,但是自定义控件默认是不支持的,所以我们要自己改,具体是将width左右都减小padding,由于我们的圆心是由width和height决定,为了不影响圆心位置,我们在画的时候加上一个padding即可,这样看起来就是画的圆形两边都缩小了,但是位置不变

重写onMeasure()

另外一个需要重写的是onMeasure(),主要用来做尺寸的测量,因为我们在activity_main中设置了wrap_content,但是自定义控件不知道wrap_content是多少,只当match_content,所以我们要在这里设定

@Override protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){ super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, 200); } else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, heightSpecSize); } else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSpecSize,200); } }

这里默认设置成200

java源代码 package com.example.makeview; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.View; public class CircleView extends View { final String TAG = "CircleView"; private int mColor =Color.RED; private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); public CircleView(Context context) { super(context); Log.d(TAG, "CircleView: First"); init(); } public CircleView(Context context, AttributeSet attributeSet) { super(context,attributeSet); TypedArray a = context.obtainStyledAttributes(attributeSet,R.styleable.CircleView); mColor = a.getColor(R.styleable.CircleView_circle_color, Color.RED); a.recycle(); Log.d(TAG, "CircleView: Second"); init(); } public CircleView(Context context, AttributeSet attributeSet, int defStyleAttr) { super(context, attributeSet, defStyleAttr); Log.d(TAG, "CircleView: Third"); init(); } private void init() { mPaint.setColor(mColor); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingLeft(); int paddingTop = getPaddingLeft(); int paddingBottom = getPaddingLeft(); int width = getWidth() - paddingLeft - paddingRight; //缩减宽高 int height = getHeight() - paddingTop - paddingBottom; int radius = Math.min(width,height)/2; canvas.drawCircle(width/2+paddingLeft,height/2+paddingBottom,radius,mPaint); } @Override protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){ super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, 200); } else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, heightSpecSize); } else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSpecSize,200); } } }
作者:小松与蘑菇



view 自定义view

需要 登录 后方可回复, 如果你还没有账号请 注册新账号