自定义 View 流程

  • 第一步,在 values 目录下面创建自定义属性的 XML,比如 attrs.xml 或 attrs_ 开头的文件名,当然文件名没有什么限制,本例选择创建 attrs.xml 文件。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleView">
        <attr name="circle_color" format="color"/>
    </declare-styleable>
</resources>

声明属性集合 CircleView ,集合里可以有很多自定义属性,format 有多种格式,reference 指资源 id,dimension 指尺寸,string、integer、boolean 指基本类型。

  • 第二步,在 View 的构造方法中解析自定义属性值并做相应处理,解析 cricle_color 属性的值,代码如下:
public CircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleView);
        mColor = a.getColor(R.styleable.CircleView_circle_color, Color.RED);
        a.recycle();
    }

首先加载自定义属性集合 CircleView ,接着解析 CircleView 属性集合中 circle_color 属性,解析完要调用 recycle 方法释放资源。

  • 第三步,在布局文件中使用自定义属性,如下所示:
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.ViewActivity">

        <com.example.sunshinexu.view.CircleView
           android:layout_width="wrap_content"
           android:layout_height="100dp"
           android:layout_margin="20dp"
           android:padding="20dp"
           app:circle_color="#00ff00"
</LinearLayout>

为了使用自定义属性,必须在布局文件中添加 schemas 声明:xmlns:app=”http://schemas.android.com/apk/res-auto” 。app 是自定义属性的前缀,可以换其他的名字,apk 后可以用 res/附加应用的包名。

  • 下面是 自定义View,CircleView 完整代码,要对 wrap_content 做特殊处理,为什么做处理,看我上一篇博客,View 的工作原理。
public class CircleView extends View {
    private static final String TAG = "CircleView";

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int mColor = Color.RED;
    public CircleView(Context context) {
        super(context);
        init();
    }

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleView);
        mColor = a.getColor(R.styleable.CircleView_circle_color, Color.RED);
        a.recycle();
        init();
    }

    public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(400,200);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(400,heightSize);
        } else if (heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSize,200);
        }
    }

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

    private void init() {
        mPaint.setColor(mColor);
    }
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页