【android自己定义控件】自己定义View属性

1、自己定义View的属性

2、在View的构造方法中获得我们自己定义的属性

3、重写onMesure

4、重写onDraw

3这个步骤不是必须,当然了大部分情况下还是须要重写的。

1、自己定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="txtName" format="string"/>
    <attr name="txtColor" format="color"/>
    <attr name="txtSize" format="dimension" />
    
    <declare-styleable name="titleStyle">
        <attr name="txtName"/>
        <attr name="txtColor"/>
        <attr name="txtSize"/>
    </declare-styleable>
</resources>

定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:

一共同拥有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;

编写的时候工具会提醒你使用哪种,不知道也能够Google搜索下


接下来就自己定义View

public class CustomTitleView extends View{

    private  String txtName;
    private int txtColor,txtSize;
    private  Paint mPaint;
    private Rect mBounds;


    public CustomTitleView(Context context) {
        this(context, null);
    }

    public CustomTitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);


    }

    public CustomTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
           //详细操作
    }
}

定义完自己定义的View ,就该调用我们自己定义的View了。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:title="http://schemas.android.com/apk/res/com.example.androidDemo"  《》
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.androidDemo.View.CustomTitleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="5dp"
        title:txtName="你好"
        title:txtColor="#ffffff"
        title:txtSize="16sp"/>
</RelativeLayout>

注意代码中的这行,自己定义命名空间,com.example.androidDemo是项目包路径

xmlns:title="http://schemas.android.com/apk/res/com.example.androidDemo"


使用自己定义命名空间:
        title:txtName="你好"
        title:txtColor="#ffffff"
        title:txtSize="16sp"


在View的构造方法中,获得我们的自己定义的样式

public class CustomTitleView extends View{

    private  String txtName;
    private int txtColor,txtSize;
    private  Paint mPaint;
    private Rect mBounds;


    public CustomTitleView(Context context) {
        this(context, null);
    }

    public CustomTitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);


    }

    public CustomTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.titleStyle,defStyleAttr,0);

        int n = typedArray.getIndexCount();

        for (int i = 0; i < n; i++){
            int attr = typedArray.getIndex(i);
            switch (attr){

                case 0:

                    txtName = typedArray.getString(attr);
                    break;
                case 1:

                    txtColor = typedArray.getColor(attr, Color.BLACK);
                    break;
                case 2:
                    txtSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                    break;

            }
        }
        typedArray.recycle();

        /**
         * 获得绘制文本的宽和高 
         */
        mPaint = new Paint();
        mPaint.setTextSize(txtSize);
        // mPaint.setColor(mTitleTextColor);
        mBounds = new Rect();
        mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int width;
            int height ;
            if (widthMode == MeasureSpec.EXACTLY)
            {
                width = widthSize;
            } else
            {
                mPaint.setTextSize(txtSize);
                mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);
                float textWidth = mBounds.width();
                int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
                width = desired;
            }

            if (heightMode == MeasureSpec.EXACTLY)
            {
                height = heightSize;
            } else
            {
                mPaint.setTextSize(txtSize);
                mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);
                float textHeight = mBounds.height();
                int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());
                height = desired;
            }



            setMeasuredDimension(width, height);


    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

        mPaint.setColor(txtColor);
        canvas.drawText(txtName, getWidth() / 2 - mBounds.width() / 2, getHeight() / 2 + mBounds.height() / 2, mPaint);

    }
}


当中

MeasureSpec.EXACTLY推断你传人的宽,高是不是精确赋值
android:layout_width="wrap_content"
 android:layout_height="wrap_content"


假设是wrap_content,

 mPaint.setTextSize(txtSize);
                mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);
                float textWidth = mBounds.width();
                int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
                width = desired;

假设是200dp这类精确的宽高值,

if (widthMode == MeasureSpec.EXACTLY)
            {
                width = widthSize;
            } 

效果图 ,是不是非常好用呢


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。