自定义视图(二)


自定义绘制

对于一个自定义视图最重要的一部分就是它的显示。

重写onDraw()

对于绘制一个自定义的view最重要的一步就是重写onDraw()函数。onDraw()函数的参数
是一个Canvas对象,view可以使用它来绘制自己。Canvas类定义了一个方法来绘制文本,线,
图片和其他几何图像。你可以在onDra()方法中使用这些方法来创建自定义的用户界面。

在你调用任何绘制方法之前,需要创建一个Paint对象。

创建绘制对象

android.graphics框架将绘制分为两个方面:
1.绘制什么,由Canvas负责
2.如何绘制,由Paint负责

例如,Canvas提供了一个方法来绘制一条线,然而Paint提供方法来定义线的颜色。Canva有一
个方法来绘制一个矩形,而Paint定义将矩形填满颜色还是留空白。简单来说,Canvas定义了你
要绘制的形状,而Paint定义了你要绘制的图像的颜色,样式,字体等属性。

因此,在你绘制之前,你需要创建一个或多个Paint对象。

private void init() {    mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    mTextPaint.setColor(mTextColor);    if (mTextHeight == 0) {        mTextHeight = mTextPaint.getTextSize();    } else {        mTextPaint.setTextSize(mTextHeight);    }      mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);    mPiePaint.setStyle(Paint.Style.FILL);    mPiePaint.setTextSize(mTextHeight);      mShadowPaint = new Paint(0);    mShadowPaint.setColor(0xff101010);    mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));      ...


在使用之前创建对象是一个重要的优化方式。对View的重新绘制是非常频繁的,很多的绘制对
象的初始化需要花费很高代价。在onDraw函数中创建绘制对象将会严重影响成像的性能。

处理Layout事件

为了恰当的绘制自定义的视图,你需要知道它的大小。复杂的自定义视图基于它的大小和形状,
通常需要执行多次布局计算。你不应该假设屏幕上视图的大小。即使只有一个应用程序使用你
的视图,这个应用程序需要处理不同的屏幕大小,多种屏幕分辨率,以及不同的屏幕方向模式。

尽管View有很多处理测量的方法,但他们中的大多数都不需要被重写。如果你的view不需要对
它的大小做特别的控制,你只需要重写一个方法:onSizeChanged()。

当你的view被首次分配一个大小,或者因为任何原因你的view的大小发生了改变,都会调用
onSizeChanged()函数。在onSizeChanged()方法中计算位置,维度和其他与你view大小
相关的值,而不是在每次绘制的时候进行计算。

当你的view被分配一个大小,布局管理器假设这个值包含了view的padding。你必须在计算view
大小的时候处理padding的值。

// Account for padding        float xpad = (float)(getPaddingLeft() + getPaddingRight());        float ypad = (float)(getPaddingTop() + getPaddingBottom());          // Account for the label        if (mShowText) xpad += mTextWidth;          float ww = (float)w - xpad;        float hh = (float)h - ypad;          // Figure out how big we can make the pie.        float diameter = Math.min(ww, hh);


如果你要精确的控制view的布局参数,实现onMeasure()方法。这个方法的参数是View.MeasureSpec,
它会告诉你,你的view的父容器期望你的view大小是多少,而且这个值是一个硬性值,或者
仅仅是一个建议值。作为一种优化,这些值被存储在一个包装的Integer中,你可以使用View.MesureSpec
来解压缩存储在每个integer中的信息。


@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    // Try for a width based on our minimum    int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();    int w = resolveSizeAndState(minw, widthMeasureSpec, 1);      // Whatever the width ends up being, ask for a height that would let the pie    // get as big as it can    int minh = MeasureSpec.getSize(w) - (int)mTextWidth + getPaddingBottom() + getPaddingTop();    int h = resolveSizeAndState(MeasureSpec.getSize(w) - (int)mTextWidth, heightMeasureSpec, 0);      setMeasuredDimension(w, h); }


在上面的代码中你需要注意下面几点:
1.计算考虑了view的padding
2.辅助方法resolveSizeAndState()被用来创建最终的宽度和高度。这个辅助方法通过比较
view的所需要的大小和传递到onMeasure()中的spec,返回一个合适的View.MeasureSpec
值。
3.onMeasure方法没有返回值。该方法通过调用setMeasuredDimension()方法来与它的结果
进行通信。调用此方法是强制性的,如果你省略了此方法的调用,View类在运行时将会跑出
异常。

绘制

一旦你有了定义创建和测量的代码,你可以实现onDraw()方法了。每一个view都会实现不
同的onDraw方法,但他们之间都会存在一些相同的操作。
1.绘制文本使用drawText()。通过调用setTypeface()指定字体,调用setColor()指定
文本的颜色。
2.使用drawRect()、drawOval()和drawArc()方法绘制原始图形。
3.使用Path类绘制负责的图形。通过向Path对象添加线和曲线定义形状,然后使用drawPath()
绘制图形。
4.通过创建LinearGradient对象来定义gradient。
5.使用drawBitmap()绘制图像。

protected void onDraw(Canvas canvas) {    super.onDraw(canvas);      // Draw the shadow    canvas.drawOval(            mShadowBounds,            mShadowPaint    );      // Draw the label text    canvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint);      // Draw the pie slices    for (int i = 0; i < mData.size(); ++i) {        Item it = mData.get(i);        mPiePaint.setShader(it.mShader);        canvas.drawArc(mBounds,                360 - it.mEndAngle,                it.mEndAngle - it.mStartAngle,                true, mPiePaint);    }      // Draw the pointer    canvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint);    canvas.drawCircle(mPointerX, mPointerY, mPointerSize, mTextPaint); }
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值