您的位置:首页 > 移动开发 > Android开发

android-Canvas and Drawables

2015-12-15 23:18 344 查看
Applications such as video games should be drawing to the Canvas on its own. However, there's more than one way to do this:

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

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:
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);

It's recommended that you ultimately draw your final graphics through a Canvas offered to you by
View.onDraw()
or
SurfaceHolder.lockCanvas()


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

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


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

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

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

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.

> The following code snippet demonstrates how to build an
ImageView
that
uses an image from drawable resources and add it to the 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);
}


> Here's some XML that defines a 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:
Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable)
res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);

> Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a 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);
}
}


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

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.

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: