`

【翻译】(71)画布和可绘画对象

 
阅读更多

【翻译】(71)画布和可绘画对象

 

see

http://developer.android.com/guide/topics/graphics/2d-graphics.html

 

原文见

http://developer.android.com/guide/topics/graphics/2d-graphics.html

 

-------------------------------

 

Canvas and Drawables

 

画布和可绘画对象

 

-------------------------------

 

In this document

 

本文目录

 

* Draw with a Canvas 用一个Canvas绘画

* On a View 在一个View上

* On a SurfaceView 在一个SurfaceView上

* Drawables 可绘画对象

* Creating from resource images 从资源图片中创建

* Creating from resource XML 从资源XML中创建

* Shape Drawable 形状可绘画对象

* Nine-patch 九宫

 

See also

 

另见

 

* OpenGL with the Framework APIs 使用框架API的OpenGL

* RenderScript 

 

-------------------------------

 

The Android framework APIs provides a set 2D drawing APIs that allow you to render your own custom graphics onto a canvas or to modify existing Views to customize their look and feel. When drawing 2D graphics, you'll typically do so in one of two ways:

 

Android框架API提供一组二维绘画API,允许你渲染你自己的自定义图形到一个画布上或者修改现存View以自定义它们的外观和感觉。当绘画二维图形时,你将通常以两种方式中的一种来做这些事情:

 

a. Draw your graphics or animations into a View object from your layout. In this manner, the drawing of your graphics is handled by the system's normal View hierarchy drawing process — you simply define the graphics to go inside the View.

 

a. 绘画你的图形或动画进一个来自你的布局的View对象。通过这种方式,你的图形的绘画被系统的正常View层级绘画过程处理——你简单地定义要进入View内的图形。

 

b. Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's onDraw() method (passing it your Canvas), or one of the Canvas draw...() methods (like drawPicture()). In doing so, you are also in control of any animation.

 

b. 直接地绘画你的图形到一个Canvas。通过这种方式,你亲自调用合适的类的onDraw()方法(把你的Canvas传给它),或Canvas的其中一个draw...()方法(像drawPicture())。通过做这些事情,你还控制任意动画。

 

Option "a," drawing to a View, is your best choice when you want to draw simple graphics that do not need to change dynamically and are not part of a performance-intensive game. For example, you should draw your graphics into a View when you want to display a static graphic or predefined animation, within an otherwise static application. Read Drawables for more information.

 

选项"a",绘画到一个View,是你的最佳选择,当你希望绘画不需要动态改变和非性能密集游戏局部的简单图形。例如,你应该绘画你的图形进一个View,当你希望显示一个静态图形或者在另外的一个静态应用程序中预定义的动画时。请阅读可绘画对象以获得更多信息。

 

Option "b," drawing to a Canvas, is better when your application needs to regularly re-draw itself. Applications such as video games should be drawing to the Canvas on its own. However, there's more than one way to do this:

 

选项"b",绘画到一个Canvas,是较好的,当你的应用程序需要定期地重新绘画它自己。应用程序诸如视频游戏(注:即电子游戏)应该自己绘画到Canvas。然而,有多于一种方式做这件事:

 

* In the same thread as your UI Activity, wherein you create a custom View component in your layout, call invalidate() and then handle the onDraw() callback.

 

* 在你的用户界面Activity的相同的线程中,不管你在哪里创建你的布局内的自定义View组件,调用invalidate()然后处理onDraw()回调。

 

* Or, in a separate thread, wherein you manage a SurfaceView and perform draws to the Canvas as fast as your thread is capable (you do not need to request invalidate()).

 

* 或者,在一个单独的线程,不管你在哪里管理一个SurfaceView并且只要你的线程的可以,尽可能快地执行对Canvas的绘画(你不需要请求invalidate())。

 

-------------------------------

 

Draw with a Canvas

 

用一个Canvas绘画

 

When you're writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn — it holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.

 

当你正在编写一个应用程序,其中你希望执行特殊化绘画和/或控制图形的动画,你应该通过用Canvas绘画来做到这一点。一个Canvas为你工作,作为对于你的图形将绘画在其上的实际表面的一个伪装,或者接口——它持有你的所有“draw”调用,通过Canvas,你的绘画被实际地执行在一个底层的Bitmap上,它被放置进窗口里面。

 

In the event that you're drawing within the onDraw() callback method, the Canvas is provided for you and you need only place your drawing calls upon it. You can also acquire a Canvas from SurfaceHolder.lockCanvas(), when dealing with a SurfaceView object. (Both of these scenarios are discussed in the following sections.) However, if you need to create a new Canvas, then you must define the Bitmap upon which drawing will actually be performed. The Bitmap is always required for a Canvas. You can set up a new Canvas like this:

 

在你正在在onDraw()回调方法里绘画的情况下,Canvas被提供给你,而你只需要放置你的绘画调用在它上面。你还可以从SurfaceHolder.lockCanvas()中获得一个Canvas,当处理SurfaceView对象时。(这两个场景都在以下章节中被讨论。)然而,如果你需要创建一个新Canvas,那么你必须定义绘画将实际被执行在其上的Bitmap。Canvas总是需要一个Bitmap。你可以配置一个新Canvas像这样:

 

-------------------------------

 

Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

Canvas c = new Canvas(b);

 

-------------------------------

 

Now your Canvas will draw onto the defined Bitmap. After drawing upon it with the Canvas, you can then carry your Bitmap to another Canvas with one of the Canvas.drawBitmap(Bitmap,...) methods. It's recommended that you ultimately draw your final graphics through a Canvas offered to you by View.onDraw() or SurfaceHolder.lockCanvas() (see the following sections).

 

现在你的Canvas将绘画到已定义的Bitmap上。在用Canvas绘画在它之上后,然后你可以用其中一个Canvas.drawBitmap(Bitmap,...)方法搬运你的Bitmap到另一个Canvas。建议你最后通过由View.onDraw()或SurfaceHolder.lockCanvas()提供给你的Canvas,绘画你的最终图形(见以下章节)。

 

The Canvas class has its own set of drawing methods that you can use, like drawBitmap(...), drawRect(...), drawText(...), and many more. Other classes that you might use also have draw() methods. For example, you'll probably have some Drawable objects that you want to put on the Canvas. Drawable has its own draw() method that takes your Canvas as an argument.

 

Canvas类拥有它自己的绘画方法集合,你可以使用它们,像drawBitmap(...),drawRect(...),drawText(...),以及其它更多。你可能使用的其它类也拥有draw()方法。例如,你将可能有一些Drawable对象,你希望放置它们到Canvas上。Drawable拥有它自己的draw()方法,它传入你的Canvas作为一个参数。

 

On a View

 

在一个View上

 

If your application does not require a significant amount of processing or frame-rate speed (perhaps for a chess game, a snake game, or another slowly-animated application), then you should consider creating a custom View component and drawing with a Canvas in View.onDraw(). The most convenient aspect of doing so is that the Android framework will provide you with a pre-defined Canvas to which you will place your drawing calls.

 

如果你的应用程序不需要一个巨大数量的处理或帧率速度(可能对于一个棋类游戏,一个蛇类游戏,或另一个缓慢动画化应用程序),那么你应该考虑创建一个自定义View组件并且在View.onDraw()中用一个Canvas绘画。这样做最大的便利方面是,Android框架将把一个预定义Canvas提供给你,而你将把你的绘画调用放置其中。

 

To start, extend the View class (or descendant thereof) and define the onDraw() callback method. This method will be called by the Android framework to request that your View draw itself. This is where you will perform all your calls to draw through the Canvas, which is passed to you through the onDraw() callback.

 

为了开始,请扩展View类(或它的后代类)并且定义onDraw()回调方法。这个方法将被Android框架调用以请求你的View绘画它自己。在这里你将执行你的所有调用以通过Canvas来绘画,而Canvas是通过onDraw()回调传递给你。

 

The Android framework will only call onDraw() as necessary. Each time that your application is prepared to be drawn, you must request your View be invalidated by calling invalidate(). This indicates that you'd like your View to be drawn and Android will then call your onDraw() method (though is not guaranteed that the callback will be instantaneous).

 

Android框架将在需要时才调用onDraw()。每当你的应用程序准备被绘画时,你必须通过调用invalidate()请求你的View被无效化。这指示你希望你的View被绘画而随后Android将调用你的onDraw()方法(虽然不保证回调将是即时的)。

 

Inside your View component's onDraw(), use the Canvas given to you for all your drawing, using various Canvas.draw...() methods, or other class draw() methods that take your Canvas as an argument. Once your onDraw() is complete, the Android framework will use your Canvas to draw a Bitmap handled by the system.

 

在你的View组件的onDraw()内,使用给你的Canvas以用于你的所有绘画,使用不同的Canvas.draw...()方法,或者其它类的传入你的Canvas作为一个参数的draw()方法。一旦你的onDraw()完成,Android框架将使用你的Canvas来绘画一个被系统处理的Bitmap。

 

-------------------------------

 

Note: In order to request an invalidate from a thread other than your main Activity's thread, you must call postInvalidate().

 

注意:为了从一个不同于你的主Activity线程的线程中请求一次无效化,你必须调用postInvalidate()。

 

-------------------------------

 

For information about extending the View class, read Building Custom Components.

 

想获得关于扩展View类的信息,请阅读构建自定义组件。

 

For a sample application, see the Snake game, in the SDK samples folder: <your-sdk-directory>/samples/Snake/.

 

想获得一个例子应用程序,请阅读贪吃蛇游戏,在SDK的samples文件夹中:<你的SDK目录>/samples/Snake/。

 

On a SurfaceView

 

在一个SurfaceView上

 

The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy. The aim is to offer this drawing surface to an application's secondary thread, so that the application isn't required to wait until the system's View hierarchy is ready to draw. Instead, a secondary thread that has reference to a SurfaceView can draw to its own Canvas at its own pace.

 

SurfaceView是一个特殊的View子类,它提供View层级内的一个专用绘画表面。目的是提供这个绘画表面给一个应用程序的第二线程,使应用程序不需要等待直至系统的View层级准备绘画。取而代之,一个引用到SurfaceView的第二线程可以以它自己的步伐来绘画到它自己的Canvas。

 

To begin, you need to create a new class that extends SurfaceView. The class should also implement SurfaceHolder.Callback. This subclass is an interface that will notify you with information about the underlying Surface, such as when it is created, changed, or destroyed. These events are important so that you know when you can start drawing, whether you need to make adjustments based on new surface properties, and when to stop drawing and potentially kill some tasks. Inside your SurfaceView class is also a good place to define your secondary Thread class, which will perform all the drawing procedures to your Canvas.

 

为了开始,你需要创建一个扩展自SurfaceView的新类。该类还应该实现SurfaceHolder.Callback。这个子类是一个接口,它将用关于底层Surface的信息通知你,诸如它何时被创建,被改变,或被销毁。这些事件非常重要,使你知道你什么时候可以开始绘画,你是否需要基于新的表面属性作出调整,以及什么时候停止绘画和隐式地杀死一些任务。在你的SurfaceView类内还是定义你的第二Thread类的好地方,它将对你的Canvas执行所有绘画过程。

 

Instead of handling the Surface object directly, you should handle it via a SurfaceHolder. So, when your SurfaceView is initialized, get the SurfaceHolder by calling getHolder(). You should then notify the SurfaceHolder that you'd like to receive SurfaceHolder callbacks (from SurfaceHolder.Callback) by calling addCallback() (pass it this). Then override each of the SurfaceHolder.Callback methods inside your SurfaceView class.

 

不是直接处理Surface对象,而是你应该通过一个SurfaceHolder来处理它。所以,当你的SurfaceView被初始化时,通过SurfaceView获得SurfaceHolder。然后你应该通过调用addCallback()(把this传给它)通知SurfaceHolder你希望接收SurfaceHolder回调(来自SurfaceHolder.Callback)。然后在你的SurfaceView内覆盖每个SurfaceHolder.Callback方法。

 

In order to draw to the Surface Canvas from within your second thread, you must pass the thread your SurfaceHandler and retrieve the Canvas with lockCanvas(). You can now take the Canvas given to you by the SurfaceHolder and do your necessary drawing upon it. Once you're done drawing with the Canvas, call unlockCanvasAndPost(), passing it your Canvas object. The Surface will now draw the Canvas as you left it. Perform this sequence of locking and unlocking the canvas each time you want to redraw.

 

为了在你的第二线程中绘画到Surface的Canvas,你必须把SurfaceHandler传给线程并且用lockCanvas()接收该Canvas。你现在可以持有SurfaceHolder给你的Canvas并且在它上面做你必要的绘画。一旦你做完对Canvas的绘画,请调用unlockCanvasAndPost(),传给它你的Canvas对象。现在Surface将绘画Canvas当你离开它时。每次你希望重画时请执行画布的这个锁定和解锁序列。

 

-------------------------------

 

Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.

 

注意:在每次你从SurfaceHolder中取出Canvas的轮次时,Canvas的前一次状态将被保留。为了正确地动画你的图形,你必须重画整个表面。例如,你可以通过用drawColor()填充一种颜色或者用drawBitmap()设置背景图片,清空前一次的Canvas状态。否则,你将看到你之前执行过的绘画痕迹。

 

-------------------------------

 

For a sample application, see the Lunar Lander game, in the SDK samples folder: <your-sdk-directory>/samples/LunarLander/. Or, browse the source in the Sample Code section.

 

想获得示例应用程序,参见登月飞行器游戏,在SDK示例文件夹中:<你的SDK目录>/samples/LunarLander/。或者,浏览示例代码章节中的源代码。

 

-------------------------------

 

Drawables

 

可绘画对象

 

Android offers a custom 2D graphics library for drawing shapes and images. The android.graphics.drawable package is where you'll find the common classes used for drawing in two-dimensions.

 

Android提供一个自定义二维图形库用于绘画形状和图片。在android.graphics.drawable包中你将找到用于在二维中绘画的一般类。

 

This document discusses the basics of using Drawable objects to draw graphics and how to use a couple subclasses of the Drawable class. For information on using Drawables to do frame-by-frame animation, see Drawable Animation.

 

本文讨论使用Drawable对象绘画图形的基础以及如何使用两个Drawable类的子类。想获得关于使用Drawable进行逐帧动画的信息,请参见可绘画对象动画。

 

A Drawable is a general abstraction for "something that can be drawn." You'll discover that the Drawable class extends to define a variety of specific kinds of drawable graphics, including BitmapDrawable, ShapeDrawable, PictureDrawable, LayerDrawable, and several more. Of course, you can also extend these to define your own custom Drawable objects that behave in unique ways.

 

一个Drawable是一个“可以被绘画的某些东西”的通用抽象。你将发现Drawable扩展以定义各种可绘画图形的特殊类型,包括BitmapDrawable,ShapeDrawable,PictureDrawable,LayerDrawable,以及其它一些。当然,你还可以扩展这些类以定义你自己的自定义Drawable东西,它以独特的方式行为。

 

There are three ways to define and instantiate a Drawable: using an image saved in your project resources; using an XML file that defines the Drawable properties; or using the normal class constructors. Below, we'll discuss each the first two techniques (using constructors is nothing new for an experienced developer).

 

这里有三种定义和实例化Drawable的方式:使用保存在你的工程资源中的图片;使用一个定义Drawable属性的XML文件;或者使用正常的类构造函数。下面,我们将讨论前面两中技术中的每种(使用构造函数对于一个有经验的开发者来说不是新鲜事)。

 

Creating from resource images

 

从资源图片中创建

 

A simple way to add graphics to your application is by referencing an image file from your project resources. Supported file types are PNG (preferred), JPG (acceptable) and GIF (discouraged). This technique would obviously be preferred for application icons, logos, or other graphics such as those used in a game.

 

添加图形到你的应用程序的一种简单方式是通过从你的工程资源中引用一个图片文件。支持的文件类型有PNG(首选),JPG(可接受)以及GIF(不鼓励)。这项技术将明显地倾向用于应用程序图标,徽记,或其它图形诸如在游戏中被使用的那些图形。

 

To use an image resource, just add your file to the res/drawable/ directory of your project. From there, you can reference it from your code or your XML layout. Either way, it is referred using a resource ID, which is the file name without the file type extension (E.g., my_image.png is referenced as my_image).

 

为了使用一个图片资源,只要添加你的文件到你的工程的res/drawable/目录。从那里,你可以从你的代码或你的XML布局中引用它。通过这两种方式之一,它使用一个资源ID来被引用,而它是不带文件类型扩展名的文件名(例如,my_image.png被引用为my_image)。

 

-------------------------------

 

Note: Image resources placed in res/drawable/ may be automatically optimized with lossless image compression by the aapt tool during the build process. For example, a true-color PNG that does not require more than 256 colors may be converted to an 8-bit PNG with a color palette. This will result in an image of equal quality but which requires less memory. So be aware that the image binaries placed in this directory can change during the build. If you plan on reading an image as a bit stream in order to convert it to a bitmap, put your images in the res/raw/ folder instead, where they will not be optimized.

 

注意:放置在res/drawable/中的图片资源可能在构建过程期间被aapt工具用无损图片压缩自动优化。例如,一个不需要多于256色的真彩PNG可能被转换为一个带颜色调色板的8位PNG。它将导致一个相同品质的图片,但它需要较少的内存。所以请意识到放置在这个目录中的图片二进制文件可以在构建期间改变。如果你打算读取一个图片作为一个位流以便转换它为一个位图,那么请你改为放置你的图片在res/raw/文件夹中,在那里它们将不被优化。

 

-------------------------------

 

Example code

 

示例代码

 

The following code snippet demonstrates how to build an ImageView that uses an image from drawable resources and add it to the layout.

 

以下代码片段演示如何构建一个ImageView,它使用一个来自可绘画资源的图片并添加它到布局。

 

-------------------------------

 

  LinearLayout mLinearLayout;

 

  protected void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

 

  // Create a LinearLayout in which to add the ImageView

  // 创建一个LinearLayout,准备添加ImageView到它里面

  mLinearLayout = new LinearLayout(this);

 

  // Instantiate an ImageView and define its properties

  // 实例化一个ImageView并且定义它的属性

  ImageView i = new ImageView(this);

  i.setImageResource(R.drawable.my_image);

  i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions 设置ImageView的范围以匹配Drawable的尺寸

  i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT,

  LayoutParams.WRAP_CONTENT));

 

  // Add the ImageView to the layout and set the layout as the content view

  // 添加ImageView到布局并设置布局作为内容视图

  mLinearLayout.addView(i);

  setContentView(mLinearLayout);

  }

 

-------------------------------

 

In other cases, you may want to handle your image resource as a Drawable object. To do so, create a Drawable from the resource like so:

 

在其它情况下,你可能希望处理你的图片资源作为一个Drawable对象。为了做到这点,从资源中创建一个Drawable,就像这样:

 

-------------------------------

 

    Resources res = mContext.getResources();

    Drawable myImage = res.getDrawable(R.drawable.my_image);

 

-------------------------------

 

-------------------------------

 

Note: Each unique resource in your project can maintain only one state, no matter how many different objects you may instantiate for it. For example, if you instantiate two Drawable objects from the same image resource, then change a property (such as the alpha) for one of the Drawables, then it will also affect the other. So when dealing with multiple instances of an image resource, instead of directly transforming the Drawable, you should perform a tween animation.

 

注意:在你的工程中每个唯一的资源可以只维护一个状态,不管你可以为它实例化多少不同的对象。例如,如果你从相同图片资源中实例化两个Drawable,那么改变其中一个Drawable的一个属性(诸如透明度),那么它也将影响其它。所以当处理一个图片资源的多个实例时,你不应该直接变换Drawable,而是应该执行一个补间动画。

 

-------------------------------

 

Example XML

 

示例XML

 

The XML snippet below shows how to add a resource Drawable to an ImageView in the XML layout (with some red tint just for fun).

 

下面的XML代码片段展示如何添加一个资源Drawable到XML布局中的一个ImageView(带有一些红色色彩只是为了好玩)。

 

-------------------------------

 

      <ImageView

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:tint="#55ff0000"

      android:src="@drawable/my_image"/>

 

-------------------------------

 

For more information on using project resources, read about Resources and Assets.

 

想获得关于使用工程资源的更多信息,请阅读有关资源和资产的内容。

 

Creating from resource XML

 

从资源XML中创建

 

By now, you should be familiar with Android's principles of developing a User Interface. Hence, you understand the power and flexibility inherent in defining objects in XML. This philosophy caries over from Views to Drawables. If there is a Drawable object that you'd like to create, which is not initially dependent on variables defined by your application code or user interaction, then defining the Drawable in XML is a good option. Even if you expect your Drawable to change its properties during the user's experience with your application, you should consider defining the object in XML, as you can always modify properties once it is instantiated.

 

到目前为止,你应该熟悉了Android开发一个用户界面的原则。因此,你了解在XML中从定义对象中继承而来的威力和灵活性。这个哲学从View搬到Drawable(注:caries应该是carries的笔误)。如果你希望创建一个Drawable对象,它最初不依赖于被你的应用程序代码或用户交互定义的变量,那么定义Drawable在XML中是好选择。即便你期望你的Drawable在用户体验你的应用程序期间改变它的属性,你还是应该考虑在XML中定义对象,因为你总是可以修改属性一旦它被实例化。

 

Once you've defined your Drawable in XML, save the file in the res/drawable/ directory of your project. Then, retrieve and instantiate the object by calling Resources.getDrawable(), passing it the resource ID of your XML file. (See the example below.)

 

一旦你已经在XML中定义好你的Drawable,请保存文件在你的工程的res/drawable/目录中。然后,通过调用Resources.getDrawable()取出和实例化对象,把你的XML文件的资源ID传给它。(见下面的示例。)

 

Any Drawable subclass that supports the inflate() method can be defined in XML and instantiated by your application. Each Drawable that supports XML inflation utilizes specific XML attributes that help define the object properties (see the class reference to see what these are). See the class documentation for each Drawable subclass for information on how to define it in XML.

 

任何支持inflate()方法的Drawable子类都可以被定义在XML中和被你的应用程序实例化。每个支持XML解压的Drawable利用特定的XML属性帮助定义对象属性(见类参考文档以查看这些属性是什么)。参见每个Drawable子类的类文档以获得关于如何在XML中定义它的信息。

 

Example

 

示例

 

Here's some XML that defines a TransitionDrawable:

 

这里有一些XML定义一个TransitionDrawable:

 

-------------------------------

 

      <transition xmlns:android="http://schemas.android.com/apk/res/android">

      <item android:drawable="@drawable/image_expand">

      <item android:drawable="@drawable/image_collapse">

      </transition>

 

-------------------------------

 

With this XML saved in the file res/drawable/expand_collapse.xml, the following code will instantiate the TransitionDrawable and set it as the content of an ImageView:

 

伴随保存在文件res/drawable/expand_collapse.xml中的XML,以下代码将实例化TransitionDrawable并设置它作为一个ImageView的内容:

 

-------------------------------

 

      Resources res = mContext.getResources();

      TransitionDrawable transition = (TransitionDrawable)

res.getDrawable(R.drawable.expand_collapse);

      ImageView image = (ImageView) findViewById(R.id.toggle_image);

      image.setImageDrawable(transition);

 

-------------------------------

 

Then this transition can be run forward (for 1 second) with:

 

然后这个过渡可以被向前运行(每一秒),使用以下代码:

 

-------------------------------

 

transition.startTransition(1000);

 

-------------------------------

 

Refer to the Drawable classes listed above for more information on the XML attributes supported by each.

 

参考上面列举的Drawable类以获得关于每个类支持的XML属性的更多信息。

 

-------------------------------

 

Shape Drawable

 

形状可绘画对象

 

When you want to dynamically draw some two-dimensional graphics, a ShapeDrawable object will probably suit your needs. With a ShapeDrawable, you can programmatically draw primitive shapes and style them in any way imaginable.

 

当你希望动态地绘画一些二维图形时,一个ShapeDrawable对象将正确地适合你的需要。使用一个ShapeDrawable,你可以用程序绘画原始形状并且以任意可想象的方式样式化它们。

 

A ShapeDrawable is an extension of Drawable, so you can use one where ever a Drawable is expected — perhaps for the background of a View, set with setBackgroundDrawable(). Of course, you can also draw your shape as its own custom View, to be added to your layout however you please. Because the ShapeDrawable has its own draw() method, you can create a subclass of View that draws the ShapeDrawable during the View.onDraw() method. Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a View:

 

ShapeDrawable是Drawable的扩展,所以你可以在一个期待Drawable的地方使用它——可能对于通过setBackgroundDrawable()设置的一个View的背景。当然,你还可以绘画你的形状作为它自己的自定义View,以被添加到你的布局不管你如何放置(注:此处please疑误)。因为ShapeDrawable拥有它自己的draw()方法,所以你可以创建一个View子类,它在View.onDraw()方法期间绘画该ShapeDrawable。这里有View类的一个基本扩展正好做到这点,以绘画一个ShapeDrawable作为一个View:

 

-------------------------------

 

      public class CustomDrawableView extends View {

      private ShapeDrawable mDrawable;

 

      public CustomDrawableView(Context context) {

      super(context);

 

      int x = 10;

      int y = 10;

      int width = 300;

      int height = 50;

 

      mDrawable = new ShapeDrawable(new OvalShape());

      mDrawable.getPaint().setColor(0xff74AC23);

      mDrawable.setBounds(x, y, x + width, y + height);

      }

 

      protected void onDraw(Canvas canvas) {

      mDrawable.draw(canvas);

      }

      }

 

-------------------------------

 

In the constructor, a ShapeDrawable is defines as an OvalShape. It's then given a color and the bounds of the shape are set. If you do not set the bounds, then the shape will not be drawn, whereas if you don't set the color, it will default to black.

 

在构造函数中,一个ShapeDrawable被定义为一个OvalShape。然后它被给予一个颜色并且形状的范围被设置。如果你不设置范围,那么形状将不被绘画,然而如果你不设置颜色,它将默认被设置为黑色。

 

With the custom View defined, it can be drawn any way you like. With the sample above, we can draw the shape programmatically in an Activity:

 

带有被定义的自定义View,它可以以你喜欢的任意方式绘画。对于上面的例子,我们可以在Activity中用程序绘画图形:

 

-------------------------------

 

      CustomDrawableView mCustomDrawableView;

 

      protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      mCustomDrawableView = new CustomDrawableView(this);

 

      setContentView(mCustomDrawableView);

      }

 

-------------------------------

 

If you'd like to draw this custom drawable from the XML layout instead of from the Activity, then the CustomDrawable class must override the View(Context, AttributeSet) constructor, which is called when instantiating a View via inflation from XML. Then add a CustomDrawable element to the XML, like so:

 

如果你希望从XML布局中绘画这个自定义可绘画对象而非从Activity中,那么CustomDrawable类必须覆盖View(Context, AttributeSet)构造函数,它在通过解压XML实例化一个View的时候被调用。然后添加一个CustomDrawable元素到XML,像这样:

 

-------------------------------

 

      <com.example.shapedrawable.CustomDrawableView

      android:layout_width="fill_parent"

      android:layout_height="wrap_content"

      />

 

-------------------------------

 

The ShapeDrawable class (like many other Drawable types in the android.graphics.drawable package) allows you to define various properties of the drawable with public methods. Some properties you might want to adjust include alpha transparency, color filter, dither, opacity and color.

 

ShapeDrawable类(像android.graphics.drawable包中其它许多Drawable类型那样)允许你用public方法定义可绘画对象的不同属性。你可能希望调整的一些属性包括alpha透明度,颜色滤镜,抖动,不透明度以及颜色。

 

You can also define primitive drawable shapes using XML. For more information, see the section about Shape Drawables in the Drawable Resources document.

 

你还可以使用XML定义原始的可绘画形状。想获得更多信息,请参见在可绘画资源文档中关于形状可绘画对象的章节。

 

-------------------------------

 

Nine-patch

 

九宫

 

A NinePatchDrawable graphic is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the View in which you have placed it as the background. An example use of a NinePatch is the backgrounds used by standard Android buttons — buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border. It must be saved with the extension .9.png, and saved into the res/drawable/ directory of your project.

 

一个NinePatchDrawable图形是一个可拉伸位图图片,Android将自动地改变它的大小以适应你放进去的作为背景的View内容。九宫的一个示例用途是标准Android按钮使用的背景——按钮必须拉伸以适应不同长度的字符串。一个九宫可绘画对象是一个标准PNG图片,它包含一个额外的一像素宽边线。它必须用扩展名.9.png保存,并且保存进你的工程的res/drawable/目录中。

 

The border is used to define the stretchable and static areas of the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide black line(s) in the left and top part of the border (the other border pixels should be fully transparent or white). You can have as many stretchable sections as you want: their relative size stays the same, so the largest sections always remain the largest.

 

边线被用于定义图片的可拉伸和静态区域。你通过在边界的左和顶部分绘画一条(或多条)一像素宽的黑线以指出一个可拉伸部件(其它边线像素应该是完全透明或白色)。你可以拥有如你所愿地多的可拉伸部件:它们的相对大小保持相同,所以最大的部件总是保持最大。

 

You can also define an optional drawable section of the image (effectively, the padding lines) by drawing a line on the right and bottom lines. If a View object sets the NinePatch as its background and then specifies the View's text, it will stretch itself so that all the text fits inside only the area designated by the right and bottom lines (if included). If the padding lines are not included, Android uses the left and top lines to define this drawable area.

 

你还可以通过在右线和底线上绘画一条线来定义图片的一个可选的可绘画部件(简单说,就是内边距线)。如果一个View对象设置九宫作为它的背景,并且然后指定该View的文本,它将拉伸它自身以便让所以文本只适应于通过右线和底线指定的区域内(如果包含有它)。如果不包含有内边距线,那么Android使用左线和顶线以定义这个可绘画区域。

 

To clarify the difference between the different lines, the left and top lines define which pixels of the image are allowed to be replicated in order to stretch the image. The bottom and right lines define the relative area within the image that the contents of the View are allowed to lie within.

 

为了澄清不同线间的区别,左线和顶线定义图片的哪些像素允许被复制以便拉伸图形。底线和右线在图片内定义View的内容被允许平放在的相对区域。

 

Here is a sample NinePatch file used to define a button:

 

这里是一个示例九宫文件,它被用于定义一个按钮:

 

-------------------------------

 

(图略:

上图:可拉伸区域

下图:内边距盒子(可选)

 

-------------------------------

 

This NinePatch defines one stretchable area with the left and top lines and the drawable area with the bottom and right lines. In the top image, the dotted grey lines identify the regions of the image that will be replicated in order to stretch the image. The pink rectangle in the bottom image identifies the region in which the contents of the View are allowed. If the contents don't fit in this region, then the image will be stretched so that they do.

 

这个九宫用左线和顶线定义一个可拉伸区域以及用底线和右线定义可绘画区域。在上图中,灰色虚线标识将被复制以便拉伸图片的图片区域。下图中粉红色矩形标识View的内容被允许放在其中的区域。如果内容不适合这个区域,那么图片将被拉伸它以便让它适应这个区域。

 

The Draw 9-patch tool offers an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It even raises warnings if the region you've defined for the stretchable area is at risk of producing drawing artifacts as a result of the pixel replication.

 

绘画九宫工具提供一个非常便利的方式创建你的九宫图片,使用一个所见即所得(注:What You See Is What You Get的简称)图形编辑器。它甚至发出警告,如果你为可拉伸区域定义的区域有造成由于像素复制导致的绘画失真(注:维基称为Compression artifact,中文意思是“压缩失真”)的危险。

 

Example XML

 

示例XML

 

Here's some sample layout XML that demonstrates how to add a NinePatch image to a couple of buttons. (The NinePatch image is saved as res/drawable/my_button_background.9.png

 

这里有一些示例布局XML,它们演示如何添加一个九宫图片到两个按钮。(九宫图片被保存为res/drawable/my_button_background.9.png)(注:此处缺少一个括号)

 

-------------------------------

 

<Button id="@+id/tiny"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentTop="true"

        android:layout_centerInParent="true"

        android:text="Tiny"

        android:textSize="8sp"

        android:background="@drawable/my_button_background"/>

 

<Button id="@+id/big"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentBottom="true"

        android:layout_centerInParent="true"

        android:text="Biiiiiiig text!"

        android:textSize="30sp"

        android:background="@drawable/my_button_background"/>

 

-------------------------------

 

Note that the width and height are set to "wrap_content" to make the button fit neatly around the text.

 

注意宽度和高度被设置为"wrap_content"以使按钮刚好合适地包围在文本外。

 

Below are the two buttons rendered from the XML and NinePatch image shown above. Notice how the width and height of the button varies with the text, and the background image stretches to accommodate it.

 

下面是两个从上面展示的XML和九宫图片中渲染的按钮。注意按钮的宽度和高度如何随文本而变化,以及背景图片拉伸以适应它。

 

-------------------------------

 

(图略:

左:小(文本)

右:大文本!

 

-------------------------------

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 14 Feb 2012 21:12

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)

 

(本人翻译质量欠佳,请以官方最新内容为准,或者参考其它翻译版本:

* ソフトウェア技術ドキュメントを勝手に翻訳

http://www.techdoctranslator.com/android

* Ley's Blog

http://leybreeze.com/blog/

* 农民伯伯

http://www.cnblogs.com/over140/

* Android中文翻译组

http://androidbox.sinaapp.com/


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics