我的自定义View之旅(二)

本周把安卓开发艺术探索的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;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();
    }
  • 在测量方法中获取到长宽等一些属性

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等

猜你喜欢

转载自blog.csdn.net/asffghfgfghfg1556/article/details/80204641