`

【翻译】(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/


分享到:
评论

相关推荐

    基于HTML5的同步手绘板主要功能设计与实现.pdf

    在本文的同步手绘板设计中,模块化思想被用来组织和划分不同的功能,如绘画工具、画布管理、颜色处理等,这样可以提高代码的可读性和可维护性。 【同步手绘板】是本文的主要研究对象,它是一种基于Web的应用,利用...

    WPF 开源二维绘画小工具 GeometryToolDemo 项目.rar

    - 在WPF中,资源可以通过`ResourceDictionary`进行集中管理和重用,这有助于保持代码的整洁性和可维护性。 6. **依赖属性** - WPF的依赖属性系统是数据绑定的基础,它允许属性的值在不同对象之间传播,并提供了...

    设计模式-画笔程序

    在编程领域,设计模式是一种被广泛认可的解决常见问题的最佳实践。"设计模式-画笔程序"这个项目可能是一个利用了多种设计...设计模式不仅使代码结构清晰,还提高了代码的可重用性和可维护性,是软件开发中的重要实践。

    《iPad应用开发实战》画板程序源码

    为了实现撤销/重做,开发者可能采用了命令设计模式,将每个绘图动作视为一个可执行和可撤销的命令对象。每当用户执行一个新的绘图操作,系统都会保存当前状态,并将其添加到历史记录中。撤销操作就是回退到前一状态...

    head_first_design_patterns.zip

    书中通过画笔和画布的例子解释了如何解耦颜色的实现和绘画工具的使用。 10. **组合模式(Composite)**:将对象组合成树形结构以表示“部分-整体”的层次结构。例如,书中展示了如何使用组合模式来构建一棵由简单和...

    nomadcode_practice:用Vanilla JS制成的绘画板

    通过原生API,开发者可以更直接地操作DOM(文档对象模型),处理事件,实现动画等,从而提升代码的执行效率和可维护性。 二、绘画板的基础架构 1. HTML布局:绘画板通常由一个大的canvas元素构成,它是图形绘制的...

    2015良心系列_JAVA版画图板程序源码

    6. **颜色和样式**:Java提供了`Color`类来表示颜色,用户可以选择不同颜色进行绘画。此外,还可以设置线条宽度、填充等样式。 7. **用户交互**:程序可能还包含了菜单或工具栏,让用户选择绘图工具、改变颜色或...

    画图板--Java课程设计.doc

    在Java课程设计中,学生被要求实现一个"画图板"项目,这是一个基于Java编程语言的简单绘画应用程序。这个应用旨在模仿Windows操作系统中的画图工具,提供基本的绘图和图像处理功能。以下是该设计的主要知识点: 1. ...

    Go-pocketplace与朋友在同一个canvas上绘制像素

    通过Ajax或者WebSocket技术,前端与后端实时通信,更新画布视图,使用户能即时看到自己和朋友的绘画成果。 7. **用户认证与权限管理** 在多人协作的场景下,用户认证和权限管理是必不可少的。可以采用JWT(JSON ...

    MFC画图板详细代码1

    为了保持代码的清晰和可维护性,通常会遵循MVC(Model-View-Controller)设计模式,将数据处理、界面显示和用户交互逻辑分开。此外,可能会采用工厂模式来创建绘图工具,单例模式来管理全局资源。 通过理解和掌握...

    C# 实现画图软件

    - 添加一个`PictureBox`控件,这是我们的画布,用户将在这里进行绘画操作。 - 创建一个`MenuStrip`,在其中添加“文件”菜单,包含“打开”、“保存”等选项。 - 添加一个`ColorDialog`控件,用于实现调色板功能...

    清华大学张思民Java第6章.ppt

    每个图形对象,通常是`java.awt.Component`的子类,都有一个`paint(Graphics g)`方法,用于在其上进行绘画。`Graphics`类提供了如`drawLine()`、`drawRect()`、`drawOval()`和`drawArc()`等方法,用于绘制直线、矩形...

    exercise1_soldier866_exercise1_win32application_画图软件_

    面向对象编程在这里意味着类的设计和实例化,例如,一个`Canvas`类用来表示画布,`Pen`类代表画笔,`Color`类管理颜色,以及`Shape`类家族来表示不同类型的图形。 在实现过程中,开发者可能需要学习和应用Win32 API...

    QT5+VS2015制作的画图程序源代码

    QGraphicsView提供了一个可缩放和可滚动的视图,而QGraphicsScene是放置图形对象的区域。它们可以方便地处理复杂的图形操作,如拖放、旋转、缩放等。 5. **Visual Studio 2015集成开发环境**:在VS2015中配置和构建...

    MFC画图程序

    使用MFC可以大大简化Windows应用的开发过程,提高代码的可读性和可维护性。 2. **窗口与设备上下文**: 在MFC中,窗口对象(CWnd)是所有可视元素的基础。画图程序通常会在窗口上创建一个画布,这个画布是设备上...

    仿WINDOWS画图

    这个项目展示了如何使用Java编程语言来构建一个基本的图形编辑器,允许用户进行绘画操作,如绘制线条、图形等。通过这个项目,开发者可以深化对Java GUI(图形用户界面)设计和事件处理的理解。 【描述】描述中提到...

    PYTHON_GAME_19画画.zip

    7. **面向对象编程 (OOP)**:Python 支持 OOP,游戏中的各个组件(如画笔、画布、颜色等)可以被设计为类,这样可以更好地封装和复用代码。 8. **条件语句和循环**:在处理用户输入和绘制图形时,可能会用到 `if` ...

    模拟windows画图板程序

    在编码过程中,我们需要遵循面向对象编程的原则,将各个功能模块化,确保代码的可读性和可维护性。同时,良好的错误处理和用户界面设计也是提高程序质量的关键。 开发完成后,通过调试和测试确保程序的稳定性和功能...

    c# visual studio 2005 制作高仿真画图程序

    C#是由微软开发的一种面向对象的编程语言,它被设计用于.NET框架,提供了高效、安全和可维护的代码。Visual Studio 2005是微软的一个集成开发环境(IDE),支持多种编程语言,包括C#,并提供了强大的调试工具和项目...

Global site tag (gtag.js) - Google Analytics