本周把安卓开发艺术探索的View部分看了一下,综合着自己的理解再写一个超级简单的View,不过对各方面理解更深了
思路
- 先看需求,需要画一个特定大小的背景,再在背景上画一个特定大小,圆心特定的圆
- 那么,首先要解决的我们自定义出我们这个VIew自有的属性,然后再获取到用户设置的属性值
- 拿到那些值后,按照我们的规则进行处理,比如说,背景应该怎么放置呀,圆应该放在哪里这些东西,
- 然后再去把这些背景啊 圆啊画出来即可
实现
- 自定义属性
- 在values文件夹下新建attrs.xml文件,当然这名字随便取都可以,这里只是attrs这个名字是大家都这么写,所以就。。。
- 关于这个的一些细节,在我的上一篇博客中有讲到
<resources>
<declare-styleable name="MyView2">
<attr name="backColor" format="color"/>
<attr name="circleRadius" format="float"/>
<attr name="circleColor" format="color"/>
</declare-styleable>
</resources>
public MyView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr)
//获取布局文件属性的值
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyView2)
int n = typedArray.getIndexCount()
for(int i = 0
int attr = typedArray.getIndex(i)
switch (attr){
case R.styleable.MyView2_backColor:
backColor = typedArray.getColor(attr,Color.GRAY)
break
case R.styleable.MyView2_circleColor:
circleColor = typedArray.getColor(attr,Color.RED)
break
case R.styleable.MyView2_circleRadius:
circleRadius = typedArray.getFloat(attr,20.0f)
break
}
}
typedArray.recycle()
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthModel = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightModel = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if(widthModel == MeasureSpec.AT_MOST){
width = 200;
}else {
width = widthSize;
}
if(heightModel == MeasureSpec.AT_MOST){
height = 200;
}else {
height = heightSize;
}
paddingTop = getPaddingTop();
paddingBottom = getPaddingBottom();
paddingLeft = getPaddingLeft();
paddingRight = getPaddingRight();
}
- 这里要对长宽模式补充一下说明
- 一般AT_MOST表示你设置的是wrap_Content,这个时候就需要去设置一个默认值,或者是根据父控件给你分配的空间大小去设置一个合适的值
- 一般EXACTLY表示的是Match_parent或者一个确定的值,这个时候直接就去拿到measureSpec.getSize(MeasureSpec)就可以了
- 另一个不太常用,一般是系统控件用的,我们不需要考虑
- 拿到这些值之后,接下来就是把他画出来
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(backColor);
Rect rect = new Rect(0,0,width,height);
canvas.drawRect(rect,mPaint);
mPaint.setColor(circleColor);
canvas.drawCircle((width+paddingRight+paddingLeft)/2,(height+paddingBottom+paddingTop)/2,circleRadius,mPaint);
}
- 至此,这个超级简单的view就完成了
- 最后贴上我的view完整代码
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by 杨豪 on 2018/5/5.
*/
public class MyView2 extends View {
private int backColor = Color.GRAY;
private int circleColor = Color.RED;
private float circleRadius = 30f;
private Paint mPaint = new Paint();
public MyView2(Context context) {
this(context,null);
}
public MyView2(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyView2);
int n = typedArray.getIndexCount();
for(int i = 0;i < n ;i++){
int attr = typedArray.getIndex(i);
switch (attr){
case R.styleable.MyView2_backColor:
backColor = typedArray.getColor(attr,Color.GRAY);
break;
case R.styleable.MyView2_circleColor:
circleColor = typedArray.getColor(attr,Color.RED);
break;
case R.styleable.MyView2_circleRadius:
circleRadius = typedArray.getFloat(attr,20.0f);
break;
}
}
typedArray.recycle();
}
private int width;
private int height;
private int paddingTop;
private int paddingBottom;
private int paddingLeft;
private int paddingRight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthModel = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightModel = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if(widthModel == MeasureSpec.AT_MOST){
width = 200;
}else {
width = widthSize;
}
if(heightModel == MeasureSpec.AT_MOST){
height = 200;
}else {
height = heightSize;
}
paddingTop = getPaddingTop();
paddingBottom = getPaddingBottom();
paddingLeft = getPaddingLeft();
paddingRight = getPaddingRight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(backColor);
Rect rect = new Rect(0,0,width,height);
canvas.drawRect(rect,mPaint);
mPaint.setColor(circleColor);
canvas.drawCircle((width+paddingRight+paddingLeft)/2,(height+paddingBottom+paddingTop)/2,circleRadius,mPaint);
}
}
总结
- 在看过一遍开发艺术探索后,对view的各项机能有所了解后,发现其实view入门也挺简单的
- 首先在values文件夹下定义出我们自己的view属性文件
- 然后在View源代码中获取到属性值
- 在测量方法中获取长宽等属性
- 在Draw方法中将我们的控件画出来
注意,测量的时候需要考虑到wrap_content,padding等