自定义控件一、

本文参考鸿神: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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值