博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Custom Drawing 自定义绘制
阅读量:4046 次
发布时间:2019-05-24

本文共 6952 字,大约阅读时间需要 23 分钟。

The most important part of a custom view is its appearance. Custom drawing can be easy or complex according to your application's needs. This lesson covers some of the most common operations.           http://blog.csdn.net/sergeycao

Override onDraw()

The most important step in drawing a custom view is to override the method. The parameter to is a object that the view can use to draw itself. The class defines methods for drawing text, lines, bitmaps, and many other graphics primitives. You can use these methods in to create your custom user interface (UI).

Before you can call any drawing methods, though, it's necessary to create a object. The next section discusses in more detail.

Create Drawing Objects

The framework divides drawing into two areas:

  • What to draw, handled by
  • How to draw, handled by .

For instance, provides a method to draw a line, while provides methods to define that line's color. has a method to draw a rectangle, while defines whether to fill that rectangle with a color or leave it empty. Simply put, defines shapes that you can draw on the screen, while defines the color, style, font, and so forth of each shape you draw.

So, before you draw anything, you need to create one or more objects. The PieChart example does this in a method called init, which is called from the constructor:

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));   ...

Creating objects ahead of time is an important optimization. Views are redrawn very frequently, and many drawing objects require expensive initialization. Creating drawing objects within your method significantly reduces performance and can make your UI appear sluggish.

Handle Layout Events

In order to properly draw your custom view, you need to know what size it is. Complex custom views often need to perform multiple layout calculations depending on the size and shape of their area on screen. You should never make assumptions about the size of your view on the screen. Even if only one app uses your view, that app needs to handle different screen sizes, multiple screen densities, and various aspect ratios in both portrait and landscape mode.

Although has many methods for handling measurement, most of them do not need to be overridden. If your view doesn't need special control over its size, you only need to override one method: .

is called when your view is first assigned a size, and again if the size of your view changes for any reason. Calculate positions, dimensions, and any other values related to your view's size in , instead of recalculating them every time you draw. In the PieChart example, is where the PieChart view calculates the bounding rectangle of the pie chart and the relative position of the text label and other visual elements.

When your view is assigned a size, the layout manager assumes that the size includes all of the view's padding. You must handle the padding values when you calculate your view's size. Here's a snippet from PieChart.onSizeChanged() that shows how to do this:

// 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);

If you need finer control over your view's layout parameters, implement . This method's parameters are values that tell you how big your view's parent wants your view to be, and whether that size is a hard maximum or just a suggestion. As an optimization, these values are stored as packed integers, and you use the static methods of to unpack the information stored in each integer.

Here's an example implementation of . In this implementation, PieChart attempts to make its area big enough to make the pie as big as its label:

@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);}

There are three important things to note in this code:

  • The calculations take into account the view's padding. As mentioned earlier, this is the view's responsibility.
  • The helper method is used to create the final width and height values. This helper returns an appropriate value by comparing the view's desired size to the spec passed into .
  • has no return value. Instead, the method communicates its results by calling . Calling this method is mandatory. If you omit this call, the class throws a runtime exception.

Draw!

Once you have your object creation and measuring code defined, you can implement . Every view implements differently, but there are some common operations that most views share:

  • Draw text using . Specify the typeface by calling , and the text color by calling .
  • Draw primitive shapes using , , and . Change whether the shapes are filled, outlined, or both by calling .
  • Draw more complex shapes using the class. Define a shape by adding lines and curves to a object, then draw the shape using . Just as with primitive shapes, paths can be outlined, filled, or both, depending on the .
  • Define gradient fills by creating objects. Call to use your on filled shapes.
  • Draw bitmaps using .

For example, here's the code that draws PieChart. It uses a mix of text, lines, and shapes.

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);}
你可能感兴趣的文章
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>
mint/ubuntu安装搜狗输入法
查看>>
C++动态申请数组和参数传递问题
查看>>
opencv学习——在MFC中读取和显示图像
查看>>
Matlab与CUDA C的混合编程配置出现的问题及解决方案
查看>>
如何将PaperDownloader下载的文献存放到任意位置
查看>>
C/C++中关于动态生成一维数组和二维数组的学习
查看>>
JVM最简生存指南
查看>>
Java的对象驻留
查看>>
JVM并发机制探讨—内存模型、内存可见性和指令重排序
查看>>
如何构建高扩展性网站
查看>>