自定义控件一、

来源:互联网 发布:迈阿密热线知乎 编辑:程序博客网 时间:2024/06/11 14:01

本文参考鸿神:http://blog.csdn.net/lmj623565791/article/category/2680591. 仅作个人动手总结.
1. 自定义View的属性.
2. 在View的构造方法中获取各个属性.
3. 重写onMesure()方法.
4. 重写onLayout()方法
5. 重写OnDraw()方法.

第一个简单自定义控件的实现

  • 新建attrs.xml文件,在该文件中定义控件的各个属性

    <?xml version="1.0" encoding="utf-8" ?><resources>    <!--format:string,color,demension,integer,enum,reference,float,boolean,fraction,flag-->    <attr name="titleText" format="string" />    <attr name="titleColor" format="color" />    <attr name="titleSize" format="dimension" />    <declare-styleable name="CatfaceTextView">        <attr name="titleText" />        <attr name="titleColor" />        <attr name="titleSize" />    </declare-styleable></resources>
  • 自定义类继承目标控件,实现相关方法

    public class CatfaceTextView extends TextView {    // 自定义控件的属性    private String titleText;    private int titleColor, titleSize;    // 初始化控件内容的范围    private Rect rect = new Rect();    // 初始化画笔    private Paint paint = new Paint();    public CatfaceTextView(Context context) {        this(context, null);    }    public CatfaceTextView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CatfaceTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        /** 获取自定义控件的属性 */        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CatfaceTextView, defStyleAttr, 0);        int indexCount = typedArray.getIndexCount();        for (int i = 0; i < indexCount; i++) {            int attr = typedArray.getIndex(i);            switch (attr) {                case R.styleable.CatfaceTextView_titleText:                    titleText = typedArray.getString(attr);                    break;                case R.styleable.CatfaceTextView_titleColor:                    titleColor = typedArray.getColor(attr, Color.argb(255, 0, 0, 0)); // 默认字体颜色黑色                    break;                case R.styleable.CatfaceTextView_titleSize:                    titleSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); // 默认大小16sp                    break;            }            /** 给当前控件设置监听事件:点击更换控件内容 */            this.setOnClickListener(new OnClickListener() {                @Override public void onClick(View view) {                    titleText = new Random().nextInt(1000) + "";                    postInvalidate();                }            });        }        typedArray.recycle();        /** 获取控件内容的宽高 */        paint.setTextSize(titleSize);        paint.getTextBounds(titleText, 0, titleText.length(), rect);    }    // 以下介绍MeasureSpec的三个属性值    // EXACTLY:一般是设置了明确的值或者是MATCH_PARENT    // AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT    // UNSPECIFIED:表示子布局想要多大就多大,很少使用    @Override /** 初始化执行一次 */    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        Log.d("sequency", "mesure");        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int width, height;        if (widthMode == MeasureSpec.EXACTLY) {            width = widthSize;        } else { // 当使用wrap_content包裹时重新确认控件宽高            paint.setTextSize(titleSize);            paint.getTextBounds(titleText, 0, titleText.length(), rect);            float textWidth = rect.width();            int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());            width = desired;        }        if (heightMode == MeasureSpec.EXACTLY) {            height = heightSize;        } else {            paint.setTextSize(titleSize);            paint.getTextBounds(titleText, 0, titleText.length(), rect);            float textHeight = rect.height();            int desired = (int) (getPaddingTop() + getPaddingBottom() + textHeight);            height = desired;        }        setMeasuredDimension(width, height);    }    @Override /** 初始化执行一次 */    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        Log.d("sequency", "layout");    }    @Override  /** 每次绘制都会执行 */    protected void onDraw(Canvas canvas) {        Log.d("sequency", "draw");        /** 填充控件背景 */        paint.setColor(Color.argb(255, 255, 0, 0));        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);        /** 绘制内容及确定文本相对控件的位置 */        paint.setColor(titleColor);        // 确定文本相对控件的左下角坐标        canvas.drawText(titleText, getWidth() / 2 - rect.width() / 2, getHeight() / 2 + rect.height() / 2, paint);    }}
  • xml布局文件中定义

    <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    <!-- 必须声明命名空间! -->    xmlns:catface="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">    <catface.myview01.view.CatfaceTextView        android:layout_centerInParent="true"        android:layout_width="150dp"        android:layout_height="100dp"        catface:titleText="999"        catface:titleColor="#ff0"        catface:titleSize="36sp"/></RelativeLayout>
  • 效果

    这里写图片描述


0 0
原创粉丝点击