Canvas and Drawables
Android的框架API提供了一组二维绘图API,让您呈现自己的自定义图形到画布或修改现有的视图来定制自己的外观和感觉的。当绘制2D图形,你会通常以两种方式做到这一点:
画出你的图形或动画到从布局视图对象。在这种方式下,图形的绘制是由系统的正常查看层次拉丝工艺处理 - 您只需定义图形去查看里面。
直接画出你的图形到画布上。这样一来,你亲自调用相应的类的OnDraw()方法(它传递你的Canvas),或帆布之一绘制...()方法(如画绘画())。这样一来,你也是任何动画的控制权。
选项“a”引到View,是您最佳的选择,当你想绘制简单的图形不需要动态改变,是不是性能密集型游戏的一部分。例如,当你想显示静态图形或预定义的动画,一个原本静态的应用程序中,你应该绘制图形到一个视图。阅读绘图资源以获取更多信息。
选项“B”,绘制到一个Canvas,不如当应用程序需要定期重新绘制本身。应用,如视频游戏,应借鉴到自身的画布。然而,有这样做不止一种方法:
在同一个线程你的UI活动,其中创建在布局自定义视图组件,将无效(),然后处理的onDraw()回调。
或者,在一个单独的线程,其中你管理一个SurfaceView并执行提请画布一样快,你的线程能够(你不需要申请无效())。
用帆布画
当你写的,你想进行专业的作图和/或控制图形的动画的应用程序,你应该通过一个绘图画布这样做。画布为你工作的幌子,或接口,实际表面,在其图形将被吸引 - 它拥有所有的“画图”的电话。通过画布,图形实际上是在一个基本的位图,它被放置在窗口中执行。
在你的的onDraw()回调方法中借鉴的情况下,画布是为你,你只需要放置在其上绘图的电话。您还可以获取来自SurfaceHolder.lockCanvas一个Canvas(),具有SurfaceView对象打交道时。 (这两种情况都在下面的章节中讨论)。但是,如果你需要创建一个新的画布,那么你必须定义在其绘图将被实际执行位图。位图总是需要一个Canvas。您可以设置一个新的Canvas是这样的:
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b);现在你的画布将绘制到定义位图。与画布后,它绘制后,你就可以带着你的位图到另一个画布与Canvas.drawBitmap之一(位图,...)方法。它建议最终通过)由View.onDraw()或SurfaceHolder.lockCanvas(提供给你一个Canvas(见下文)绘制图形决赛。
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); }在其他情况下,你可能要处理图像资源作为可绘制对象。要做到这一点,创建像这样的一个资源绘制对象:
Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable.my_image);注:项目中的每个独特的资源可以只维护一个状态,无论你可能有多少种不同的对象实例化它。例如,如果你从相同的图像资源实例2拖拉的对象,然后更改属性(如Alpha)的可绘之一,那么它也将影响其他。因此,与一个图像资源的多个实例打交道时,而不是直接转化绘制对象,您应该执行补间动画。
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#55ff0000" android:src="@drawable/my_image"/>有关使用项目资源的更多信息,请阅读资源和资产。
<transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/image_expand"> <item android:drawable="@drawable/image_collapse"> </transition>有了这个XML保存在文件RES /绘制/扩展collapse.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);然后,这种转变可以向前跑(1秒)带:
transition.startTransition(1000);请参阅有关每个支持的XML属性的更多信息,上面所列的可绘制类。
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); } }在构造函数中,一个形状绘制对象被定义为一个椭圆形。它然后给出一个颜色和形状的边界被设定。如果您没有设置界限,则形状将无法绘制,而如果你不设置颜色,它会默认为黑色。
CustomDrawableView mCustomDrawableView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCustomDrawableView = new CustomDrawableView(this); setContentView(mCustomDrawableView); }如果您想从XML布局,而不是从活动得出这个自定义绘制,然后自定义绘制对象类必须重写视图(背景下,的AttributeSet)构造,通过通胀率从XML实例化一个视图时被调用。然后自定义绘制对象元素添加到XML,像这样:
<com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" />该ShapeDrawable类(像android.graphics.drawable包许多其他类型的可绘制)允许您与公共方法定义绘制的各种属性。您可能需要调整一些特性包括Alpha透明度,彩色滤光片,抖动,不透明度和颜色。
一个NinePatchDrawable图形是一个可拉伸的位图图像,它的Android会自动调整以适应你所把它作为背景查看的内容。一个例子使用九补丁是标准的Android按键使用的背景 - 按钮必须延伸,以适应不同长度的字符串。阿九补丁绘是一个标准的PNG图像,其中包括一个额外的1个像素宽的边框。它必须与扩展.9.png被保存,并保存到你的项目的RES /绘制/目录下。
边界用于定义图像的伸缩性和静止区域。你表明通过绘制一个(或多个)中的边界的左侧和顶部部分可拉伸部分1个像素宽的黑线(多个)(其他边界像素应该是充分透明的或白色)。只要你想,你可以有很多伸展部分:其相对规模保持不变,所以最大的部分始终保持最大的。
您还可以通过画线的右侧和底部行定义图像(有效,填充线)的一个可选的可绘制部分。如果一个视图对象设置NinePatch为背景,然后指定查看的文本,这将让所有的文字只能由右侧和底部线(如果有)指定的区域内适合舒展自己。如果不包括填充线,Android使用左侧和顶部行定义该可拉伸区域。
澄清不同行之间的差异,左侧和顶部行定义该图像的像素被允许以拉伸图像被复制。底部和右侧行定义了图像内的相对面积,该视图中的内容被允许之内。
这里是用来定义按钮样品NinePatch文件:
此NinePatch定义与左,顶线和与底部和右线被拉伸区域的一个拉伸区域。在顶部图像中,点状线确定将为了拉伸图像被复制的图像的区域。底图像中的粉红色矩形标识该视图中的内容被允许的区域。如果内容不在该区域适合,则图像将被拉伸,使得他们这样做。
绘图9补丁工具提供了一个非常方便的方法来创建你的NinePatch的图像,使用所见即所得的图形编辑器。它甚至提出了警告,如果您为拉伸区域定义的区域是在生产图纸文物为像素复制的结果的风险。
示例XML
以下是演示如何将NinePatch图像添加到几个按钮的一些示例XML布局。 (该NinePatch图像保存为RES /绘制/ 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”,使该按钮适合整齐周围的文本。