我的自定义View之旅(一)

打算好好学一学自定义控件,然后就尽量写一下连载博客吧

先从自定义View开始

  • 先说一下今天的自定义VIew实现的功能
  • 就是像TextView一样能显示文字,即可
  • 贪多嚼不烂,一步一步慢慢来

一,定义自己View的属性

  • 当我们需要使用一个成品View的时候,总会在xml文件里面设置它的好多好多属性,所以第一步先来看看自定义属性吧
  • 在value文件夹下的attrs.xml(没有这个文件则新建)文件下,创建新的declare-styleable结点,然后在这个结点中写上自己想要定义的属性,如下
<declare-styleable name="MyTextView">
    <attr name="titleText" format="string"/>
    <attr name="titleTextColor" format="color"/>
    <attr name="titleTextSize" format="dimension"/>
</declare-styleable>
  • declare-styleable结点后的name跟的是你的定义的view的名字
  • 内部子项的name是你打算定义的属性的名字,后面的format是你这个属性的类型

二,自定义View类

  • 定义自己的View类,他可以继承自现成的View,也可以直接继承View或者VIewGroup
  • 我先定义一个继承自View的类,这样我们的VIew内容就可以自行发挥了
  • 然后在类里面,有几个方法需要重写,今天关注的是构造函数,onMeasure(),onDraw()这三个方法
  • 第一个构造函数是在生成View的时候调用,从构造方法中我们可以得到别人写在xml文件中对我们的VIew的一些属性的设置参数
  • 第二个方法测量,顾名思义,主要负责测量我们View的大小的
  • 第三个方法绘制,就是绘制出我们的View啦
  • 由于我只是第一次写自定义View,第一次就先写这么多吧,接下来看一下代码
public class MyTextView extends View{

    private String mTitleText;
    private int mTitleTextColor;
    private int mTitleTextSize;
    /**
     * 绘制时控制文本的的绘制范围,一个矩形,刚好能装下设置的文字的大小,就是说一个矩形刚好装下一个文字
     */
    private Rect mBound;
    //画笔
    private Paint mPaint;
    public MyTextView(Context context) {
        this(context,null);
    }

    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //从attrs中获取我们定义在R.styleable.MyTextView中的属性被别人设置的值
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView,defStyleAttr,0);
        int n = typedArray.getIndexCount();
        for (int i = 0;i < n;i++){
            int attr = typedArray.getIndex(i);
            switch (attr){
                case R.styleable.MyTextView_titleText:
                    mTitleText = typedArray.getString(attr);
                    break;
                case R.styleable.MyTextView_titleTextColor:
                    mTitleTextColor = typedArray.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.MyTextView_titleTextSize:
                //第二个参数为默认值
                    mTitleTextSize = typedArray.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,
                                    getResources().getDisplayMetrics()));
                    break;
            }
        }
        //这个获取参数这个容器是要被回收的,毕竟有借有还再借不难嘛
        typedArray.recycle();

        mPaint = new Paint();
        mPaint.setColor(mTitleTextColor);
        mPaint.setTextSize(mTitleTextSize);
        mBound = new Rect();
        //这句不是很懂
        mPaint.getTextBounds(mTitleText,0,mTitleText.length(),mBound);

        //为我们的控件设置点击事件
        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                //点击事件
            }
        });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //获取长宽样式和长宽值
    //样式有三种,这个会在下一篇博客中讲到
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;
        if(widthMode == MeasureSpec.EXACTLY){
            width = widthSize;
        }else {
            //测量文字所占的width
            //这是画笔的字体的大小
            mPaint.setTextSize(mTitleTextSize);
            //获取得到的文字边界,放进mBound这个矩形内,所以文字所占的width就是mBound的width
            mPaint.getTextBounds(mTitleText,0,mTitleText.length(),mBound);
            float textWidth = mBound.width();
            //view的width = 左边内边距 + 文字Width + 右边内边距
            width = (int)(getPaddingLeft() + textWidth + getPaddingRight());
        }

        if( heightMode == MeasureSpec.EXACTLY){
            height = heightSize;
        }else {
            //测量文字所占的height
            //这是画笔的字体的大小
            mPaint.setTextSize(mTitleTextSize);
            //获取得到的文字边界,放进mBound这个矩形内,所以文字所占的width就是mBound的width
            mPaint.getTextBounds(mTitleText,0,mTitleText.length(),mBound);
            float textHeight = mBound.height();
            //view的height = 左边内边距 + 文字height + 右边内边距
            height = (int)(getPaddingTop() + textHeight + getPaddingBottom());
        }
        //设置大小
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.BLUE);
        //左  上  右   下
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);
        mPaint.setColor(mTitleTextColor);
        //这个方法也会在下一篇博客中讲到
        canvas.drawText(mTitleText,getWidth()/2 - mBound.width()/2,getHeight()/2 + mBound.height()/ 2,mPaint);
    }
}
  • 大概就是这个简单的样子了,先获取参数,然后测量控件应该具有的大小,最后将这个控件画出来
  • 嗯,因为时间原因,我明天再仔细探索一下其中一些参数的具体东西,具体细节将写在下一篇博客中
  • 注:我是菜鸟,大神勿喷

猜你喜欢

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