2D Graphics (Android官方文档中文版)

日期: 2011-04-29
 

简述

Android提供了一个特制的2D图形库,用于图形和图片的绘制和动画效果.  android.graphics.drawable 和 android.view.animation 包中包含了用于2D绘制和动画制作的通用类.

本文介绍了在你的Android应用中的图形的绘制.我们将讨论使用Drawable对象绘制图形的基本概念, 如何使用Drawable类的一些子类,以及如何创建动画: 单个图形的动画(移动,缩放,旋转),或一组图像的动画(类似卷轴动画)


Drawables

Drawable 是一个"可以被绘制的"事物的一般抽象. 你将发现Drawable类被扩展定义了一系列各种专门的可绘制图形, 包括BitmapDrawable, ShapeDrawable, PictureDrawable, LayerDrawable, 以及更多. 当然, 你也可以继承来定义属于你的独一无二的自定义的Drawable对象.

存在3种方法来定义和实例化一个Drawable: 使用保存在你的项目资源中的图片; 使用一个定义了Drawable属性的XML文件; 或者使用普通的类构造函数. 下面,我们将讨论前2种技术.

从资源图片中创建

支持文件格式: PNG(推荐),JPG(可接受) 和 GIF(不推荐). 此种方法明显地比较适合用于应用程序图标, logo, 或者其他图片例如游戏中用到的那些静态图片.

要使用图片资源, 只需将你的文件添加到你的项目的 res/drawable/ 文件夹. 这样一来,你就可以从你的代码或者你的XML布局中引用它. 不管怎样, 最好使用资源ID, 通常是不带扩展名的文件名.(如: my_image.png 文件使用 my_image引用)

注意: 放在 res/drawable/ 的图片资源在编译过程中可能会被aapt工具自动优化(无损)压缩. 例如, 一个不需要大于256色的真彩PNG, 可能会被转换成一个带调色板的8位PNG. 这样做的结果是保持相同的质量的情况下,只需更少的内存. 因此,目录里的二进制图片在编译期间可能会被改变. 如果你计划将图片作为一个比特流读入,并将其转成一个bitmap,那么请将图片放到 res/raw/ 文件夹, 这样他们不会被优化.

例子代码: 下面的代码片段展示了如何自drawable资源创建一个ImageView,并将它添加到layout.

LinearLayout mLinearLayout;   

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Create a LinearLayout in which to add the ImageView
  mLinearLayout = new LinearLayout(this);
  // Instantiate an ImageView and define its properties
  ImageView i = new ImageView(this);
  i.setImageResource(R.drawable.my_image);
  i.setAdjustViewBounds(true);
  // set the ImageView bounds to match the Drawable's dimensions
  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
  mLinearLayout.addView(i);
  setContentView(mLinearLayout);
}

另外, 若要将图片资源作为一个Drawable对象来处理, 按如下方式从资源创建一个Drawable:

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

注意: 项目中每一个唯一的资源只能维护一个状态, 而不管你为它实例化多少个不同的对象. 举个例子, 如果你从相同的图片资源实例化2个Drawable对象,当改变其中一个Drawable的某个属性(例如alpha), 那么同样会影响另一个. 因此,当处理一个图片资源的多个实例时, 最好不要直接进行Drawable的变换, 此时应当使用tween animation. 

XML举例 如下的XML片段展示了如何在XML布局中添加一个Drawable资源到一个ImageView.

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#55ff0000"
android:src="@drawable/my_image"/>

从资源XML创建.

如果要创建一个Drawable对象, 而它起初并不依赖于app代码中定义的变量,或者并不在用户交互过程中诞生, 那么将这个Drawable定义在XML中是一个好的选择. 甚至即使有在app的用户交互期间动态改变Drawable的属性情况, 也可以考虑将对象定义在XML中,因为实例化后, 总是可以修改属性.

在XML中定义Drawable后,  将文件保存到项目的 res/drawable/ 目录. 然后通过调用Resources.getDrawable()获取并实例化对象, 将XML文件的资源ID传入.(参见后面的例子)

支持inflate()方法的Drawable子类都可以在XML中定义,并可以被你的应用实例化. 每一个支持XML inflation的Drawable,都可以利用特定的XML属性来定义对象属性.(相关信息可以参考类说明文档)

例子 这里是定义一个TransitionDrawable的XML:

<transition xmlns:android="http://schemas.android.com/apk/res/android"> 
  <item android:drawable="@drawable/image_expand"> 
  <item android:drawable="@drawable/image_collapse"> 
</transition>

根据保存在文件 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);

然后这个transition可以向前运行(1秒):

transition.startTransition(1000);

Shape Drawable

ShapeDrawable对象适合动态绘制2D图形. 可以用它绘制简单的形状, 并用任何想象到的方式设计它们.

ShapeDrawable是Drawable的子类, 因此可在任何接收Drawable参数的地方使用它 - 比如一个View背景,使用setBackgroundDrawable()绘制. 当然, 你也可以将你的形状作为自定义的View来绘制,然后根据自己喜好, 将其添加到你的layout. 因为ShapeDrawable拥有它自己的draw()方法, 你可以创建一个View的子类,在View.onDraw()方法期间绘制ShapeDrawable.

这里是一个基础的View类的继承的例子, 为一个View绘制ShapeDrawable:

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

构造函数中, ShapeDrawable被定义为 OvalShape. 然后设置了颜色和形状的边界. 如果不设置边界, 形状不会被绘制, 如果不设置颜色, 则默认是黑色.

接上面的例子, 在一个Activity中绘制形状:

CustomDrawableView mCustomDrawableView; 
  protected void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
mCustomDrawableView = new CustomDrawableView(this); 
 setContentView(mCustomDrawableView); 
}

如果使用XML layout来绘制这个自定义drawable, 那么CustomDrawable类必须覆写View(Context, AttributeSet)构造函数, 当从XML读取并展开一个View时会被调用. 然后添加一个CustomDrawable元素到XML, 如下:

<com.example.shapedrawable.CustomDrawableView 
 android:layout_width="fill_parent"
android:layout_height="wrap_content" />

ShapeDrawable类(和许多其他在android.graphics.drawable package包中的Drawable类型一样)允许你通过public方法定义drawable的各种属性. 一些属性你可能想要用来调节包括alpha透明处理, 颜色过滤, 抖动, 透明度以及颜色.


Nine-patch

NinePatchDrawable图像是一种可伸缩的位图图像, 将这种图像作为View的背景时, Android将自动改变其大小来适应View的内容. 一个使用NinePatch的例子是标准Android按钮所使用的背景 - 按钮必须缩放来适应不同长度的字符串. NinePatch drawable是一个包含一个额外的1像素宽的边的标准的PNG图片. 它必须被保存为扩展名: .9.png, 并且保存在你的项目的 res/drawable/ 目录.

"边" 被用来定义可伸缩部分和图像的静态区域. 通过在边(边的其他像素应该是全透明或者白色)的左边和顶部区域绘制一个(或多个)1像素宽的黑线来指出一个可伸缩的区域. 可以有想要的任意多个可伸缩区域: 他们的相对大小保持一致, 因此最大的区域总是保持最大.

你还可以通过在右边和底部的线条上绘制一条线来定义图像的可选drawable区域(实际上是填充线). 如果View对象将NinePatch设置为它的背景并且然后指定View的文本, 它将拉伸它自己,以使所有的文本适应右边和底部的线条(如果有)指定的区域中.如果没有包括填充线, Android使用左边和顶部的线条来定义可绘制区域.

阐明不同线段的不同之处: 左边和顶部的线段定义了图像的哪些像素允许被重复复制使用来达到伸缩图像的目的. 右边和底部的线段定义了图像中的相对区域, 即定义了View的内容允许显示或者放置的区域.

这里有一个简单的NinePatch例子文件, 用于定义一个按钮:

[转载]2D <wbr>Graphics <wbr>(Android官方文档中文版)

 

此NinePatch用左边的线条和顶部的线条定义了一个可拉伸区域,以及用底部的线条和右边的线条定义了可绘制区域. 上方图中, 灰色虚线标识了将会被复制的图像的区域,以达到拉伸图像的目的. 下方图中,粉色矩形标识了View的内容所允许绘制的区域. 如果内容不适合这个区域, 那么图像会被拉伸到合适为止.

绘制 9-patch 的工具提供了非常便利的方法(WYSIWYG图形编辑器)来创建NinePatch图像. 如果你为可拉伸区域定义的区域不足以支持生成的绘制的输出时,它甚至会发警告.

举例 XML 这里是一些layout XML的例子, 展示了如何添加一个NinePatch图像到一对按钮.(NinePatch图像保存在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"/>

注意,将宽和高设置成 "wrap_content", 以使按钮整洁地环绕并适应文字. 下面是从上面的XML和NinePatch图像渲染生成的2个按钮. 注意按钮的宽和高是如何随着文本而变化的, 以及背景图像是如何缩放以适应它的.

[转载]2D <wbr>Graphics <wbr>(Android官方文档中文版)

 


文档信息
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
原文网址:http://blog.sina.com.cn/s/blog_69a4fbd70100rd0r.html
最后修改时间:2011-04-29 12:10:29
原文地址:https://www.cnblogs.com/lzhitian/p/2379254.html