android学习8#--自定义View之view类简单分析

前面几节做了这么多铺垫,终于要掀开自定义view的庐山真面目了。

View绘制过程

android学习5#–自定义View之坐标系统中我就提到过View的显示必须经历Measure(测量)、Layout(布局)和Draw(绘制)过程。具体可以参考官方:How Android Draws Views

  • Measure
    绘制前通过measure()方法先做一次测量,算出自己view的width和high,官网是这么描述measure()的:The actual measurement work of a view is performed in onMeasure(int, int), called by this method. Therefore, only onMeasure(int, int) can and must be overridden by subclasses. 意思是measure()实际上是通过调用onMeasure()方法来测量。而且子类如果想自己实现测量,只能通过重写onMeasure()方法来实现自定义view的测量。
  • Layout
    经过测量后,确定再有layout()方法确定在屏幕的位置。
    官网如此说:This is the second phase of the layout mechanism. (The first is measuring). In this phase, each parent calls layout on all of its children to position them. This is typically done using the child measurements that were stored in the measure pass().
    Derived classes should not override this method. Derived classes with children should override onLayout. In that method, they should call layout on each of their children.
    主要意思是layout()方法是view绘制的第二步(第一步是测量),同时也提供了onLayout()方法给子类重写。
  • Draw
    必须经过前面的测量、布局,才能进入绘制。官网如是说:
    Manually render this view (and all of its children) to the given Canvas. The view must have already done a full layout before this function is called. When implementing a view, implement onDraw(android.graphics.Canvas) instead of overriding this method. If you do need to override this method, call the superclass version.
    意思是说draw()方法会在布局完成后调用,另外需要注意的是自定义view时,可以通过重写onDraw()方法来实现绘制,但是重写onDraw()方法时记得调用父类方法。

View类学习

了解了view的绘制过程后,我们再回到起点,既然我们自定义的view类必须继承view,有必要了解view类的构造函数,掌握了它才知道如何设计自己的view类,

  • view():查看源码如此注释说:Non-public constructor for use in testing。用于测试中的非公共构造函数。
  • view(Context context):源码如此注释说:Simple constructor to use when creating a view from code.意思是从code上创建时会调用此函数。
  • view(Context context, AttributeSet attrs):源码如此注释说:Constructor that is called when inflating a view from XML。意思是view组件是从xml上加载布局绘制时,调用此回调。
  • View(Context context, AttributeSet attrs, int defStyleAttr):跟第3种一样,只是增加了style属性设置。通过查看源码可以看出第3中构造函数最后调用的是此构造函数。因此这个接口不会在创建view时自动创建,而是认为手动加载新的style时才会调用。
  • View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) :与第4种一样,查看源码发现第3种构造函数实际调用的是此函数。一时不知道如何讲这个函数,后续碰到有用到此构造函数再说吧。

自定义view创建

到此,相信应该或多或少有了一定的概念了,先来看看本例的源码:

public class CustomText extends View {
    private Paint mPaint;
    private Rect mBound;

    private int mTextColor;
    private float mTextSize;
    private String mTextTitle;
    private Bitmap mBg;

    private static final String TAG = CustomText.class.getSimpleName();

    public CustomText(Context context) {
        super(context);
    }

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

    public CustomText(Context context, AttributeSet attrs, int defSytleAttr) {
        super(context, attrs, defSytleAttr);

        TypedArray typeArry = context.obtainStyledAttributes(attrs, R.styleable.CustomText);

        Log.d(TAG, "CustomText_texttitle: " + R.styleable.CustomText_texttitle);
        Log.d(TAG, "CustomText_textcolor: " + R.styleable.CustomText_textcolor);
        Log.d(TAG, "CustomText_textsize: " + R.styleable.CustomText_textsize);

        mTextTitle = typeArry.getString(R.styleable.CustomText_texttitle);
        mTextColor = typeArry.getColor(R.styleable.CustomText_textcolor, 0xff00ff00);
        mTextSize = typeArry.getDimension(R.styleable.CustomText_textsize, 36);
        int resourceId = typeArry.getResourceId(R.styleable.CustomText_textbackground, 0);
        mBg = BitmapFactory.decodeResource(getResources(), resourceId);
        typeArry.recycle();

        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);

        mBound = new Rect();
        mPaint.getTextBounds(mTextTitle, 0, mTextTitle.length(), mBound);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
       // mBg = Bitmap.createScaledBitmap(mBg, getMeasuredWidth(), getMeasuredHeight(), false);
      //  canvas.drawBitmap(mBg,0, 0, null);

        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(110,150,60,mPaint);

        mPaint.setColor(Color.YELLOW);
        canvas.drawCircle((float)175.5, 210, 60, mPaint);

        mPaint.setColor(Color.BLACK);
        canvas.drawCircle(245, 150, 60, mPaint);

        mPaint.setColor(Color.GREEN);
        canvas.drawCircle(311, 210, 60, mPaint);

        mPaint.setColor(Color.RED);
        canvas.drawCircle(380, 150, 60, mPaint);

        mPaint.setColor(mTextColor);
        canvas.drawText(mTextTitle, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);

    }
}

上面的三个构造函数相信不用再讲解了吧。本节就到这里吧,下节再讲讲如何真正绘制view。

参考:

http://www.jianshu.com/p/84cee705b0d3#
http://blog.csdn.net/u011733020/article/details/50849475
http://blog.chinaunix.net/uid-26885609-id-3479671.html
http://www.cnblogs.com/angeldevil/p/3479431.html#two
http://blog.csdn.net/yuzhouxiang/article/details/6958017

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值