DO NOT MERGE cherrypick from master
docs: restructure graphics docs and add hw-acceleration docs change-Id: I0f6288d1aa5430794ac672324c3e0fc7b714455d Change-Id: Ic8406a836bde5395c1bdb9aa5c50027c7c59195f
This commit is contained in:
@@ -1,296 +1,484 @@
|
||||
page.title=2D Graphics
|
||||
page.title=Canvas and Drawables
|
||||
parent.title=Graphics
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#draw-with-canvas">Draw with a Canvas</a>
|
||||
<ol>
|
||||
<li><a href="#drawables">Drawables</a>
|
||||
<li><a href="#on-view">On a View</a></li>
|
||||
<li><a href="#on-surfaceview">On a SurfaceView</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#drawables">Drawables</a>
|
||||
<ol>
|
||||
<li><a href="#drawables-from-images">Creating from resource images</a></li>
|
||||
<li><a href="#drawables-from-xml">Creating from resource XML</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#shape-drawable">Shape Drawable</a></li>
|
||||
<!-- <li><a href="#state-list">StateListDrawable</a></li> -->
|
||||
<li><a href="#nine-patch">Nine-patch</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#shape-drawable">Shape Drawable</a></li>
|
||||
<li><a href="#nine-patch">Nine-patch</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>See also</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL with the Framework
|
||||
APIs</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Android offers a custom 2D graphics library for drawing and animating shapes and images.
|
||||
The {@link android.graphics.drawable} and {@link android.view.animation}
|
||||
packages are where you'll find the common classes used for drawing and animating in two-dimensions.
|
||||
<p>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:</p>
|
||||
|
||||
<ol type="a">
|
||||
<li>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.</li>
|
||||
<li>Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's
|
||||
{@link android.view.View#onDraw onDraw()} method (passing it your Canvas), or one of the Canvas
|
||||
<code>draw...()</code> methods (like
|
||||
<code>{@link android.graphics.Canvas#drawPicture(Picture,Rect) drawPicture()}</code>). In doing so, you are also in
|
||||
control of any animation.</li>
|
||||
</ol>
|
||||
|
||||
<p>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 <a href="#drawables">Drawables</a> for more information.</li>
|
||||
</p>
|
||||
|
||||
<p>This document offers an introduction to drawing graphics in your Android application.
|
||||
We'll discuss the basics of using Drawable objects to draw
|
||||
graphics, how to use a couple subclasses of the Drawable class, and how to
|
||||
create animations that either tween (move, stretch, rotate) a single graphic
|
||||
or animate a series of graphics (like a roll of film).</p>
|
||||
<p>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:</p>
|
||||
|
||||
<ul>
|
||||
<li>In the same thread as your UI Activity, wherein you create a custom View component in
|
||||
your layout, call <code>{@link android.view.View#invalidate()}</code> and then handle the
|
||||
<code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback.</li>
|
||||
<li>Or, in a separate thread, wherein you manage a {@link android.view.SurfaceView} and
|
||||
perform draws to the Canvas as fast as your thread is capable
|
||||
(you do not need to request <code>invalidate()</code>).</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="draw-with-canvas">Draw with a Canvas</h2>
|
||||
|
||||
<p>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 {@link android.graphics.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 {@link android.graphics.Bitmap}, which is placed into the window.</p>
|
||||
|
||||
<p>In the event that you're drawing within the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code>
|
||||
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 <code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code>,
|
||||
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 {@link android.graphics.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:</p>
|
||||
<pre>
|
||||
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(b);
|
||||
</pre>
|
||||
|
||||
<p>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 <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Matrix,Paint)
|
||||
Canvas.drawBitmap(Bitmap,...)}</code> methods. It's recommended that you ultimately draw your final
|
||||
graphics through a Canvas offered to you
|
||||
by <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code> or
|
||||
<code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code> (see the following sections).</p>
|
||||
|
||||
<p>The {@link android.graphics.Canvas} class has its own set of drawing methods that you can use,
|
||||
like <code>drawBitmap(...)</code>, <code>drawRect(...)</code>, <code>drawText(...)</code>, and many more.
|
||||
Other classes that you might use also have <code>draw()</code> methods. For example, you'll probably
|
||||
have some {@link android.graphics.drawable.Drawable} objects that you want to put on the Canvas. Drawable
|
||||
has its own <code>{@link android.graphics.drawable.Drawable#draw(Canvas) draw()}</code> method
|
||||
that takes your Canvas as an argument.</p>
|
||||
|
||||
|
||||
<h3 id="on-view">On a View</h3>
|
||||
|
||||
<p>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 <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code>.
|
||||
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.</p>
|
||||
|
||||
<p>To start, extend the {@link android.view.View} class (or descendant thereof) and define
|
||||
the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> 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 {@link android.graphics.Canvas}, which is passed to you through the <code>onDraw()</code> callback.</p>
|
||||
|
||||
<p>The Android framework will only call <code>onDraw()</code> as necessary. Each time that
|
||||
your application is prepared to be drawn, you must request your View be invalidated by calling
|
||||
<code>{@link android.view.View#invalidate()}</code>. This indicates that you'd like your View to be drawn and
|
||||
Android will then call your <code>onDraw()</code> method (though is not guaranteed that the callback will
|
||||
be instantaneous). </p>
|
||||
|
||||
<p>Inside your View component's <code>onDraw()</code>, use the Canvas given to you for all your drawing,
|
||||
using various <code>Canvas.draw...()</code> methods, or other class <code>draw()</code> methods that
|
||||
take your Canvas as an argument. Once your <code>onDraw()</code> is complete, the Android framework will
|
||||
use your Canvas to draw a Bitmap handled by the system.</p>
|
||||
|
||||
<p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main
|
||||
Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p>
|
||||
|
||||
<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
|
||||
for a guide to extending a View class, and <a href="2d-graphics.html">2D Graphics: Drawables</a> for
|
||||
information on using Drawable objects like images from your resources and other primitive shapes.</p>
|
||||
|
||||
<p>For a sample application, see the Snake game, in the SDK samples folder:
|
||||
<code><your-sdk-directory>/samples/Snake/</code>.</p>
|
||||
|
||||
<h3 id="on-surfaceview">On a SurfaceView</h3>
|
||||
|
||||
<p>The {@link android.view.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.</p>
|
||||
|
||||
<p>To begin, you need to create a new class that extends {@link android.view.SurfaceView}. The class should also
|
||||
implement {@link android.view.SurfaceHolder.Callback}. This subclass is an interface that will notify you
|
||||
with information about the underlying {@link android.view.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.</p>
|
||||
|
||||
<p>Instead of handling the Surface object directly, you should handle it via
|
||||
a {@link android.view.SurfaceHolder}. So, when your SurfaceView is initialized, get the SurfaceHolder by calling
|
||||
<code>{@link android.view.SurfaceView#getHolder()}</code>. You should then notify the SurfaceHolder that you'd
|
||||
like to receive SurfaceHolder callbacks (from {@link android.view.SurfaceHolder.Callback}) by calling
|
||||
{@link android.view.SurfaceHolder#addCallback(SurfaceHolder.Callback) addCallback()}
|
||||
(pass it <var>this</var>). Then override each of the
|
||||
{@link android.view.SurfaceHolder.Callback} methods inside your SurfaceView class.</p>
|
||||
|
||||
<p>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 <code>{@link android.view.SurfaceHolder#lockCanvas() lockCanvas()}</code>.
|
||||
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
|
||||
<code>{@link android.view.SurfaceHolder#unlockCanvasAndPost(Canvas) unlockCanvasAndPost()}</code>, 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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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 <code>{@link android.graphics.Canvas#drawColor(int) drawColor()}</code> or setting a background image
|
||||
with <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Rect,RectF,Paint) drawBitmap()}</code>. Otherwise,
|
||||
you will see traces of the drawings you previously performed.</p>
|
||||
|
||||
|
||||
<p>For a sample application, see the Lunar Lander game, in the SDK samples folder:
|
||||
<code><your-sdk-directory>/samples/LunarLander/</code>. Or,
|
||||
browse the source in the <a href="{@docRoot}guide/samples/index.html">Sample Code</a> section.</p>
|
||||
|
||||
<h2 id="drawables">Drawables</h2>
|
||||
<p>Android offers a custom 2D graphics library for drawing shapes and images.
|
||||
The {@link android.graphics.drawable} package is where you'll find the common classes used for
|
||||
drawing in two-dimensions.</p>
|
||||
|
||||
<p>A {@link android.graphics.drawable.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 {@link android.graphics.drawable.BitmapDrawable}, {@link android.graphics.drawable.ShapeDrawable},
|
||||
{@link android.graphics.drawable.PictureDrawable}, {@link android.graphics.drawable.LayerDrawable}, and several more.
|
||||
Of course, you can also extend these to define your own custom Drawable objects that behave in unique ways.</p>
|
||||
<p>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 <a href="{@docRoot}guide/topics/animation/frame-animation.html">Frame-by-Frame
|
||||
Animation</a>.</p>
|
||||
|
||||
<p>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).</p>
|
||||
<p>A {@link android.graphics.drawable.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 {@link android.graphics.drawable.BitmapDrawable}, {@link
|
||||
android.graphics.drawable.ShapeDrawable}, {@link android.graphics.drawable.PictureDrawable},
|
||||
{@link android.graphics.drawable.LayerDrawable}, and several more. Of course, you can also extend
|
||||
these to define your own custom Drawable objects that behave in unique ways.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
|
||||
<h3 id="drawables-from-images">Creating from resource images</h3>
|
||||
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
|
||||
<p>To use an image resource, just add your file to the <code>res/drawable/</code> 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., <code>my_image.png</code> is referenced as <var>my_image</var>).</p>
|
||||
<p>To use an image resource, just add your file to the <code>res/drawable/</code> 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., <code>my_image.png</code> is referenced as <var>my_image</var>).</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Image resources placed in <code>res/drawable/</code> may be
|
||||
automatically optimized with lossless image compression by the
|
||||
<code>aapt</code> 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 <code>res/raw/</code>
|
||||
folder instead, where they will not be optimized.</p>
|
||||
<p class="note"><strong>Note:</strong> Image resources placed in <code>res/drawable/</code> may be
|
||||
automatically optimized with lossless image compression by the
|
||||
<code>aapt</code> 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
|
||||
<code>res/raw/</code> folder instead, where they will not be optimized.</p>
|
||||
|
||||
<h4>Example code</h4>
|
||||
<p>The following code snippet demonstrates how to build an {@link android.widget.ImageView} that uses an image
|
||||
from drawable resources and add it to the layout.</p>
|
||||
<p>The following code snippet demonstrates how to build an {@link android.widget.ImageView} that
|
||||
uses an image from drawable resources and add it to the layout.</p>
|
||||
<pre>
|
||||
LinearLayout mLinearLayout;
|
||||
LinearLayout mLinearLayout;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Create a LinearLayout in which to add the ImageView
|
||||
mLinearLayout = new LinearLayout(this);
|
||||
// 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));
|
||||
// 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);
|
||||
}
|
||||
</pre>
|
||||
<p>In other cases, you may want to handle your image resource as a
|
||||
{@link android.graphics.drawable.Drawable} object.
|
||||
To do so, create a Drawable from the resource like so:
|
||||
<pre>
|
||||
Resources res = mContext.getResources();
|
||||
Drawable myImage = res.getDrawable(R.drawable.my_image);
|
||||
// Add the ImageView to the layout and set the layout as the content view
|
||||
mLinearLayout.addView(i);
|
||||
setContentView(mLinearLayout);
|
||||
}
|
||||
</pre>
|
||||
<p>In other cases, you may want to handle your image resource as a
|
||||
{@link android.graphics.drawable.Drawable} object.
|
||||
To do so, create a Drawable from the resource like so:
|
||||
<pre>
|
||||
Resources res = mContext.getResources();
|
||||
Drawable myImage = res.getDrawable(R.drawable.my_image);
|
||||
</pre>
|
||||
|
||||
<p class="warning"><strong>Note:</strong> 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 <a href="#tween-animation">tween animation</a>.</p>
|
||||
<p class="warning"><strong>Note:</strong> 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 <a href="{@docRoot}guide/topics/graphics/view-animation.html#tween-animation">tween
|
||||
animation</a>.</p>
|
||||
|
||||
|
||||
<h4>Example XML</h4>
|
||||
<p>The XML snippet below shows how to add a resource Drawable to an
|
||||
{@link android.widget.ImageView} in the XML layout (with some red tint just for fun).
|
||||
<pre>
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tint="#55ff0000"
|
||||
android:src="@drawable/my_image"/>
|
||||
</pre>
|
||||
<p>For more information on using project resources, read about
|
||||
<a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</p>
|
||||
<h4>Example XML</h4>
|
||||
<p>The XML snippet below shows how to add a resource Drawable to an
|
||||
{@link android.widget.ImageView} in the XML layout (with some red tint just for fun).
|
||||
<pre>
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tint="#55ff0000"
|
||||
android:src="@drawable/my_image"/>
|
||||
</pre>
|
||||
<p>For more information on using project resources, read about
|
||||
<a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</p>
|
||||
|
||||
|
||||
<h3 id="drawables-from-xml">Creating from resource XML</h3>
|
||||
<h3 id="drawables-from-xml">Creating from resource XML</h3>
|
||||
|
||||
<p>By now, you should be familiar with Android's principles of developing a
|
||||
<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>. 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.</p>
|
||||
<p>By now, you should be familiar with Android's principles of developing a
|
||||
<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>. 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.</p>
|
||||
|
||||
<p>Once you've defined your Drawable in XML, save the file in the <code>res/drawable/</code> directory of
|
||||
your project. Then, retrieve and instantiate the object by calling
|
||||
{@link android.content.res.Resources#getDrawable(int) Resources.getDrawable()}, passing it the resource ID
|
||||
of your XML file. (See the <a href="#drawable-xml-example">example below</a>.)</p>
|
||||
<p>Once you've defined your Drawable in XML, save the file in the <code>res/drawable/</code>
|
||||
directory of your project. Then, retrieve and instantiate the object by calling
|
||||
{@link android.content.res.Resources#getDrawable(int) Resources.getDrawable()}, passing it the
|
||||
resource ID of your XML file. (See the <a href="#drawable-xml-example">example
|
||||
below</a>.)</p>
|
||||
|
||||
<p>Any Drawable subclass that supports the <code>inflate()</code> 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.
|
||||
<p>Any Drawable subclass that supports the <code>inflate()</code> 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.
|
||||
|
||||
<h4 id="drawable-xml-example">Example</h4>
|
||||
<p>Here's some XML that defines a TransitionDrawable:</p>
|
||||
<pre>
|
||||
<transition xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/image_expand">
|
||||
<item android:drawable="@drawable/image_collapse">
|
||||
</transition>
|
||||
</pre>
|
||||
<h4 id="drawable-xml-example">Example</h4>
|
||||
<p>Here's some XML that defines a TransitionDrawable:</p>
|
||||
<pre>
|
||||
<transition xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/image_expand">
|
||||
<item android:drawable="@drawable/image_collapse">
|
||||
</transition>
|
||||
</pre>
|
||||
|
||||
<p>With this XML saved in the file <code>res/drawable/expand_collapse.xml</code>,
|
||||
the following code will instantiate the TransitionDrawable and set it as the content of an ImageView:</p>
|
||||
<pre>
|
||||
Resources res = mContext.getResources();
|
||||
TransitionDrawable transition = (TransitionDrawable) res.getDrawable(R.drawable.expand_collapse);
|
||||
ImageView image = (ImageView) findViewById(R.id.toggle_image);
|
||||
image.setImageDrawable(transition);
|
||||
</pre>
|
||||
<p>Then this transition can be run forward (for 1 second) with:</p>
|
||||
<pre>transition.startTransition(1000);</pre>
|
||||
<p>With this XML saved in the file <code>res/drawable/expand_collapse.xml</code>,
|
||||
the following code will instantiate the TransitionDrawable and set it as the content of an
|
||||
ImageView:</p>
|
||||
<pre>
|
||||
Resources res = mContext.getResources();
|
||||
TransitionDrawable transition = (TransitionDrawable)
|
||||
res.getDrawable(R.drawable.expand_collapse);
|
||||
ImageView image = (ImageView) findViewById(R.id.toggle_image);
|
||||
image.setImageDrawable(transition);
|
||||
</pre>
|
||||
<p>Then this transition can be run forward (for 1 second) with:</p>
|
||||
<pre>transition.startTransition(1000);</pre>
|
||||
|
||||
<p>Refer to the Drawable classes listed above for more information on the XML attributes supported by each.</p>
|
||||
<p>Refer to the Drawable classes listed above for more information on the XML attributes
|
||||
supported by each.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="shape-drawable">Shape Drawable</h2>
|
||||
<h2 id="shape-drawable">Shape Drawable</h2>
|
||||
|
||||
<p>When you want to dynamically draw some two-dimensional graphics, a {@link android.graphics.drawable.ShapeDrawable}
|
||||
object will probably suit your needs. With a ShapeDrawable, you can programmatically draw
|
||||
primitive shapes and style them in any way imaginable.</p>
|
||||
<p>When you want to dynamically draw some two-dimensional graphics, a {@link
|
||||
android.graphics.drawable.ShapeDrawable}
|
||||
object will probably suit your needs. With a ShapeDrawable, you can programmatically draw
|
||||
primitive shapes and style them in any way imaginable.</p>
|
||||
|
||||
<p>A ShapeDrawable is an extension of {@link android.graphics.drawable.Drawable}, so you can use one where ever
|
||||
a Drawable is expected — perhaps for the background of a View, set with
|
||||
{@link android.view.View#setBackgroundDrawable(android.graphics.drawable.Drawable) setBackgroundDrawable()}.
|
||||
Of course, you can also draw your shape as its own custom {@link android.view.View},
|
||||
to be added to your layout however you please.
|
||||
Because the ShapeDrawable has its own <code>draw()</code> method, you can create a subclass of View that
|
||||
draws the ShapeDrawable during the <code>View.onDraw()</code> method.
|
||||
Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a View:</p>
|
||||
<pre>
|
||||
public class CustomDrawableView extends View {
|
||||
private ShapeDrawable mDrawable;
|
||||
<p>A ShapeDrawable is an extension of {@link android.graphics.drawable.Drawable}, so you can use
|
||||
one where ever
|
||||
a Drawable is expected — perhaps for the background of a View, set with
|
||||
{@link android.view.View#setBackgroundDrawable(android.graphics.drawable.Drawable)
|
||||
setBackgroundDrawable()}.
|
||||
Of course, you can also draw your shape as its own custom {@link android.view.View},
|
||||
to be added to your layout however you please.
|
||||
Because the ShapeDrawable has its own <code>draw()</code> method, you can create a subclass of
|
||||
View that
|
||||
draws the ShapeDrawable during the <code>View.onDraw()</code> method.
|
||||
Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a
|
||||
View:</p>
|
||||
<pre>
|
||||
public class CustomDrawableView extends View {
|
||||
private ShapeDrawable mDrawable;
|
||||
|
||||
public CustomDrawableView(Context context) {
|
||||
super(context);
|
||||
public CustomDrawableView(Context context) {
|
||||
super(context);
|
||||
|
||||
int x = 10;
|
||||
int y = 10;
|
||||
int width = 300;
|
||||
int height = 50;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
protected void onDraw(Canvas canvas) {
|
||||
mDrawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>In the constructor, a ShapeDrawable is defines as an {@link android.graphics.drawable.shapes.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.</p>
|
||||
<p>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:</p>
|
||||
<pre>
|
||||
CustomDrawableView mCustomDrawableView;
|
||||
<p>In the constructor, a ShapeDrawable is defines as an {@link
|
||||
android.graphics.drawable.shapes.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.</p>
|
||||
<p>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:</p>
|
||||
<pre>
|
||||
CustomDrawableView mCustomDrawableView;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mCustomDrawableView = new CustomDrawableView(this);
|
||||
|
||||
setContentView(mCustomDrawableView);
|
||||
}
|
||||
</pre>
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mCustomDrawableView = new CustomDrawableView(this);
|
||||
|
||||
<p>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 {@link android.view.View#View(android.content.Context, android.util.AttributeSet) 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:</p>
|
||||
<pre>
|
||||
<com.example.shapedrawable.CustomDrawableView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
</pre>
|
||||
setContentView(mCustomDrawableView);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The ShapeDrawable class (like many other Drawable types in the {@link 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.</p>
|
||||
<p>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 {@link
|
||||
android.view.View#View(android.content.Context, android.util.AttributeSet) 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:</p>
|
||||
<pre>
|
||||
<com.example.shapedrawable.CustomDrawableView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
</pre>
|
||||
|
||||
<p>The ShapeDrawable class (like many other Drawable types in the {@link
|
||||
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.</p>
|
||||
|
||||
<p>You can also define primitive drawable shapes using XML. For more information, see the
|
||||
section about Shape Drawables in the <a
|
||||
|
||||
<p>You can also define primitive drawable shapes using XML. For more information, see the
|
||||
section about Shape Drawables in the <a
|
||||
href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
|
||||
document.</p>
|
||||
document.</p>
|
||||
|
||||
<!-- TODO
|
||||
<h2 id="state-list">StateListDrawable</h2>
|
||||
<!-- TODO
|
||||
<h2 id="state-list">StateListDrawable</h2>
|
||||
|
||||
<p>A StateListDrawable is an extension of the DrawableContainer class, making it little different.
|
||||
The primary distinction is that the
|
||||
StateListDrawable manages a collection of images for the Drawable, instead of just one.
|
||||
This means that it can switch the image when you want, without switching objects. However, the
|
||||
intention of the StateListDrawable is to automatically change the image used based on the state
|
||||
of the object it's attached to.
|
||||
-->
|
||||
<p>A StateListDrawable is an extension of the DrawableContainer class, making it little
|
||||
different.
|
||||
The primary distinction is that the
|
||||
StateListDrawable manages a collection of images for the Drawable, instead of just one.
|
||||
This means that it can switch the image when you want, without switching objects. However,
|
||||
the
|
||||
intention of the StateListDrawable is to automatically change the image used based on the
|
||||
state
|
||||
of the object it's attached to.
|
||||
-->
|
||||
|
||||
<h2 id="nine-patch">Nine-patch</h2>
|
||||
<h2 id="nine-patch">Nine-patch</h2>
|
||||
|
||||
<p>A {@link android.graphics.drawable.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 <code>.9.png</code>,
|
||||
and saved into the <code>res/drawable/</code> directory of your project.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>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.</p>
|
||||
<p>
|
||||
Here is a sample NinePatch file used to define a button:
|
||||
</p>
|
||||
<img src="{@docRoot}images/ninepatch_raw.png" alt="" />
|
||||
<p>A {@link android.graphics.drawable.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
|
||||
<code>.9.png</code>,
|
||||
and saved into the <code>res/drawable/</code> directory of your project.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>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.</p>
|
||||
<p>
|
||||
Here is a sample NinePatch file used to define a button:
|
||||
</p>
|
||||
<img src="{@docRoot}images/ninepatch_raw.png" alt="" />
|
||||
|
||||
<p>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.
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
<p>The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> tool offers
|
||||
an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It
|
||||
<p>The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> 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.
|
||||
</p>
|
||||
@@ -298,7 +486,8 @@ producing drawing artifacts as a result of the pixel replication.
|
||||
<h3>Example XML</h3>
|
||||
|
||||
<p>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 <code>res/drawable/my_button_background.9.png</code>
|
||||
couple of buttons. (The NinePatch image is saved as
|
||||
<code>res/drawable/my_button_background.9.png</code>
|
||||
<pre>
|
||||
<Button id="@+id/tiny"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -318,11 +507,12 @@ couple of buttons. (The NinePatch image is saved as <code>res/drawable/my_button
|
||||
android:textSize="30sp"
|
||||
android:background="@drawable/my_button_background"/>
|
||||
</pre>
|
||||
<p>Note that the width and height are set to "wrap_content" to make the button fit neatly around the text.
|
||||
<p>Note that the width and height are set to "wrap_content" to make the button fit neatly around the
|
||||
text.
|
||||
</p>
|
||||
|
||||
<p>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
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
|
||||
522
docs/html/guide/topics/graphics/hardware-accel.jd
Normal file
522
docs/html/guide/topics/graphics/hardware-accel.jd
Normal file
@@ -0,0 +1,522 @@
|
||||
page.title=Hardware Acceleration
|
||||
parent.title=Graphics
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="#controlling">Controlling Hardware Acceleration</a></li>
|
||||
<li><a href="#determining">Determining if a View is Hardware Accelerated</a></li>
|
||||
<li><a href="#model">Android Drawing Models</a>
|
||||
|
||||
<ol>
|
||||
<li><a href="#software-model">Software-based drawing model</a></li>
|
||||
<li><a href="#hardware-model">Hardware accelerated drawing model</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#unsupported">Unsupported Drawing Operations</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#layers">View Layers</a>
|
||||
|
||||
<ol>
|
||||
<li><a href="#layers-anims">View Layers and Animations</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
<li><a href="#tips">Tips and Tricks</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>See also</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL with the Framework
|
||||
APIs</a></li>
|
||||
|
||||
<li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline is designed to
|
||||
better support hardware acceleration. Hardware acceleration carries out all drawing operations
|
||||
that are performed on a {@link android.view.View}'s canvas using the GPU.</p>
|
||||
|
||||
<p>The easiest way to enable hardware acceleration is to turn it on
|
||||
globally for your entire application. If your application uses only standard views and {@link
|
||||
android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse
|
||||
effects. However, because hardware acceleration is not supported for all of the 2D drawing
|
||||
operations, turning it on might affect some of your applications that use custom views or drawing
|
||||
calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly
|
||||
rendered pixels. To remedy this, Android gives you the option to enable or disable hardware
|
||||
acceleration at the following levels:</p>
|
||||
|
||||
<ul>
|
||||
<li>Application</li>
|
||||
|
||||
<li>Activity</li>
|
||||
|
||||
<li>Window</li>
|
||||
|
||||
<li>View</li>
|
||||
</ul>
|
||||
|
||||
<p>If your application performs custom drawing, test your application on actual hardware
|
||||
devices with hardware acceleration turned on to find any problems. The <a
|
||||
href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
|
||||
drawing operations that cannot be hardware accelerated and how to work around them.</p>
|
||||
|
||||
|
||||
<h2 id="controlling">Controlling Hardware Acceleration</h2>
|
||||
<p>You can control hardware acceleration at the following levels:</p>
|
||||
<ul>
|
||||
<li>Application</li>
|
||||
|
||||
<li>Activity</li>
|
||||
|
||||
<li>Window</li>
|
||||
|
||||
<li>View</li>
|
||||
</ul>
|
||||
|
||||
<h4>Application level</h4>
|
||||
<p>In your Android manifest file, add the following attribute to the
|
||||
<a href="{@docRoot}guide/topics/manifest/application-element.html">
|
||||
<code><application></code></a> tag to enable hardware acceleration for your entire
|
||||
application:</p>
|
||||
|
||||
<pre>
|
||||
<application android:hardwareAccelerated="true" ...>
|
||||
</pre>
|
||||
|
||||
<h4>Activity level</h4>
|
||||
<p>If your application does not behave properly with hardware acceleration turned on globally,
|
||||
you can control it for individual activities as well. To enable or disable hardware acceleration
|
||||
at the activity level, you can use the <code>android:hardwareAccelerated</code>
|
||||
attribute for the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
|
||||
<code><activity></code></a> element. The following example enables hardware acceleration
|
||||
for the entire application but disables it for one activity:</p>
|
||||
|
||||
<pre>
|
||||
<application android:hardwareAccelerated="true">
|
||||
<activity ... />
|
||||
<activity android:hardwareAccelerated="false" />
|
||||
</application>
|
||||
</pre>
|
||||
|
||||
<h4>Window level</h4>
|
||||
<p>If you need even more fine-grained control, you can enable hardware acceleration for a given
|
||||
window with the following code:</p>
|
||||
|
||||
<pre>
|
||||
getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note</strong>: You currently cannot disable hardware acceleration at
|
||||
the window level.</p>
|
||||
|
||||
<h4>View level</h4>
|
||||
|
||||
<p>You can disable hardware acceleration for an individual view at runtime with the
|
||||
following code:</p>
|
||||
|
||||
<pre>
|
||||
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note</strong>: You currently cannot enable hardware acceleration at
|
||||
the view level. View layers have other functions besides disabling hardware acceleration. See <a
|
||||
href="#layers">View layers</a> for more information about their uses.</p>
|
||||
|
||||
<h2 id="determining">Determining if a View is Hardware Accelerated</h2>
|
||||
|
||||
<p>It is sometimes useful for an application to know whether it is currently hardware
|
||||
accelerated, especially for things such as custom views. This is particularly useful if your
|
||||
application does a lot of custom drawing and not all operations are properly supported by the new
|
||||
rendering pipeline.</p>
|
||||
|
||||
<p>There are two different ways to check whether the application is hardware accelerated:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} returns
|
||||
<code>true</code> if the {@link android.view.View} is attached to a hardware accelerated
|
||||
window.</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()}
|
||||
returns <code>true</code> if the {@link android.graphics.Canvas} is hardware accelerated</li>
|
||||
</ul>
|
||||
|
||||
<p>If you must do this check in your drawing code, use {@link
|
||||
android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()} instead of {@link
|
||||
android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} when possible. When a view
|
||||
is attached to a hardware accelerated window, it can still be drawn using a non-hardware
|
||||
accelerated Canvas. This happens, for instance, when drawing a view into a bitmap for caching
|
||||
purposes.</p>
|
||||
|
||||
|
||||
<h2 id="model">Android Drawing Models</h2>
|
||||
|
||||
<p>When hardware acceleration is enabled, the Android framework utilizes a new drawing model that
|
||||
utilizes <em>display lists</em> to render your application to the screen. To fully understand
|
||||
display lists and how they might affect your application, it is useful to understand how Android
|
||||
draws views without hardware acceleration as well. The following sections describe the
|
||||
software-based and hardware-accelerated drawing models.</p>
|
||||
|
||||
<h3>Software-based drawing model</h3>
|
||||
<p>In the software drawing model, views are drawn with the following two steps:</p>
|
||||
<ol>
|
||||
<li>Invalidate the hierarchy</li>
|
||||
|
||||
<li>Draw the hierarchy</li>
|
||||
</ol>
|
||||
|
||||
<p>Whenever an application needs to update a part of its UI, it invokes {@link
|
||||
android.view.View#invalidate invalidate()} (or one of its variants) on any view that has changed
|
||||
content. The invalidation messages are propagated all the way up the view hierarchy to compute
|
||||
the regions of the screen that need to be redrawn (the dirty region). The Android system then
|
||||
draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are
|
||||
two drawbacks to this drawing model:</p>
|
||||
<ul>
|
||||
<li>First, this model requires execution of a lot of code on every draw pass. For example, if
|
||||
your application calls {@link android.view.View#invalidate invalidate()} on a button and that
|
||||
button sits on top of another view, the Android system redraws the view even though it hasn't
|
||||
changed.</li>
|
||||
<li>The second issue is that the drawing model can hide bugs in your application. Since the
|
||||
Android system redraws views when they intersect the dirty region, a view whose content you
|
||||
changed might be redrawn even though {@link android.view.View#invalidate invalidate()} was not
|
||||
called on it. When this happens, you are relying on another view being invalidated to obtain the
|
||||
proper behavior. This behavior can change every time you modify your application. Because of
|
||||
this, you should always call {@link android.view.View#invalidate invalidate()} on your custom
|
||||
views whenever you modify data or state that affects the view’s drawing code.</li>
|
||||
</ul>
|
||||
|
||||
<p class="note"><strong>Note</strong>: Android views automatically call {@link
|
||||
android.view.View#invalidate invalidate()} when their properties change, such as the background
|
||||
color or the text in a {@link android.widget.TextView}.</p>
|
||||
|
||||
<h3>Hardware accelerated drawing model</h3>
|
||||
<p>The Android system still uses {@link android.view.View#invalidate invalidate()} and {@link
|
||||
android.view.View#draw draw()} to request screen updates and to render views, but handles the
|
||||
actual drawing differently. Instead of executing the drawing commands immediately, the Android
|
||||
system records them inside display lists, which contain the output of the view hierarchy’s
|
||||
drawing code. Another optimization is that the Android system only needs to record and update
|
||||
display lists for views marked dirty by an {@link android.view.View#invalidate invalidate()}
|
||||
call. Views that have not been invalidated can be redrawn simply by re-issuing the previously
|
||||
recorded display list. The new drawing model contains three stages:</p>
|
||||
|
||||
<ol>
|
||||
<li>Invalidate the hierarchy</li>
|
||||
|
||||
<li>Record and update display lists</li>
|
||||
|
||||
<li>Draw the display lists</li>
|
||||
</ol>
|
||||
|
||||
<p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link
|
||||
android.view.View#draw draw()} method executed. To ensure that the Android system records a
|
||||
view’s display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting
|
||||
to do so causes a view to look the same even after changing it, which is an easier bug to find if
|
||||
it happens.</p>
|
||||
|
||||
<p>Using display lists also benefits animation performance because setting specific properties,
|
||||
such as alpha or rotation, does not require invalidating the targeted view (it is done
|
||||
automatically). This optimization also applies to views with display lists (any view when your
|
||||
application is hardware accelerated.) For example, assume there is a {@link
|
||||
android.widget.LinearLayout} that contains a {@link android.widget.ListView} above a {@link
|
||||
android.widget.Button}. The display list for the {@link android.widget.LinearLayout} looks like
|
||||
this:</p>
|
||||
|
||||
<ul>
|
||||
<li>DrawDisplayList(ListView)</li>
|
||||
|
||||
<li>DrawDisplayList(Button)</li>
|
||||
</ul>
|
||||
|
||||
<p>Assume now that you want to change the {@link android.widget.ListView}'s opacity. After
|
||||
invoking <code>setAlpha(0.5f)</code> on the {@link android.widget.ListView}, the display list now
|
||||
contains this:</p>
|
||||
|
||||
<ul>
|
||||
<li>SaveLayerAlpha(0.5)</li>
|
||||
|
||||
<li>DrawDisplayList(ListView)</li>
|
||||
|
||||
<li>Restore</li>
|
||||
|
||||
<li>DrawDisplayList(Button)</li>
|
||||
</ul>
|
||||
|
||||
<p>The complex drawing code of {@link android.widget.ListView} was not executed. Instead, the
|
||||
system only updated the display list of the much simpler {@link android.widget.LinearLayout}. In
|
||||
an application without hardware acceleration enabled, the drawing code of both the list and its
|
||||
parent are executed again.</p>
|
||||
|
||||
<h2 id="unsupported">Unsupported Drawing Operations</h2>
|
||||
|
||||
<p>When hardware accelerated, the 2D rendering pipeline supports the most commonly used {@link
|
||||
android.graphics.Canvas} drawing operations as well as many less-used operations. All of the
|
||||
drawing operations that are used to render applications that ship with Android, default widgets
|
||||
and layouts, and common advanced visual effects such as reflections and tiled textures are
|
||||
supported. The following list describes known operations that are <strong>not supported</strong>
|
||||
with hardware acceleration:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Canvas</strong>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.graphics.Canvas#clipPath clipPath()}</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#clipRegion clipRegion()}</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawPicture drawPicture()}</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawPosText drawPosText()}</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawTextOnPath drawTextOnPath()}</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawVertices drawVertices()}</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Paint</strong>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.graphics.Paint#setLinearText setLinearText()}</li>
|
||||
|
||||
<li>{@link android.graphics.Paint#setMaskFilter setMaskFilter()}</li>
|
||||
|
||||
<li>{@link android.graphics.Paint#setRasterizer setRasterizer()}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>In addition, some operations behave differently with hardware acceleration enabled:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Canvas</strong>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.graphics.Canvas#clipRect clipRect()}: <code>XOR</code>,
|
||||
<code>Difference</code> and <code>ReverseDifference</code> clip modes are ignored. 3D
|
||||
transforms do not apply to the clip rectangle</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawBitmapMesh drawBitmapMesh()}: colors array is
|
||||
ignored</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#drawLines drawLines()}: anti-aliasing is not
|
||||
supported</li>
|
||||
|
||||
<li>{@link android.graphics.Canvas#setDrawFilter setDrawFilter()}: can be set, but is
|
||||
ignored</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Paint</strong>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.graphics.Paint#setDither setDither()}: ignored</li>
|
||||
|
||||
<li>{@link android.graphics.Paint#setFilterBitmap setFilterBitmap()}: filtering is always
|
||||
on</li>
|
||||
|
||||
<li>{@link android.graphics.Paint#setShadowLayer setShadowLayer()}: works with text
|
||||
only</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>ComposeShader</strong>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.graphics.ComposeShader} can only contain shaders of different types (a
|
||||
{@link android.graphics.BitmapShader} and a {@link android.graphics.LinearGradient} for
|
||||
instance, but not two instances of {@link android.graphics.BitmapShader} )</li>
|
||||
|
||||
<li>{@link android.graphics.ComposeShader} cannot contain a {@link
|
||||
android.graphics.ComposeShader}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>If your application is affected by any of these missing features or limitations, you can turn
|
||||
off hardware acceleration for just the affected portion of your application by calling
|
||||
{@link android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way,
|
||||
you can still take advantage of hardware acceleratin everywhere else. See <a
|
||||
href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable and
|
||||
disable hardware acceleration at different levels in your application.
|
||||
|
||||
|
||||
|
||||
<h2 id="layers">View Layers</h2>
|
||||
|
||||
<p>In all versions of Android, views have had the ability to render into off-screen buffers,
|
||||
either by using a view's drawing cache, or by using {@link android.graphics.Canvas#saveLayer
|
||||
Canvas.saveLayer()}. Off-screen buffers, or layers, have several uses. You can use them to get
|
||||
better performance when animating complex views or to apply composition effects. For instance,
|
||||
you can implement fade effects using <code>Canvas.saveLayer()</code> to temporarily render a view
|
||||
into a layer and then composite it back on screen with an opacity factor.</p>
|
||||
|
||||
<p>Beginning in Android 3.0 (API level 11), you have more control on how and when to use layers
|
||||
with the {@link android.view.View#setLayerType View.setLayerType()} method. This API takes two
|
||||
parameters: the type of layer you want to use and an optional {@link android.graphics.Paint}
|
||||
object that describes how the layer should be composited. You can use the {@link
|
||||
android.graphics.Paint} parameter to apply color filters, special blending modes, or opacity to a
|
||||
layer. A view can use one of three layer types:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.view.View#LAYER_TYPE_NONE}: The view is rendered normally and is not backed
|
||||
by an off-screen buffer. This is the default behavior.</li>
|
||||
|
||||
<li>{@link android.view.View#LAYER_TYPE_HARDWARE}: The view is rendered in hardware into a
|
||||
hardware texture if the application is hardware accelerated. If the application is not hardware
|
||||
accelerated, this layer type behaves the same as {@link
|
||||
android.view.View#LAYER_TYPE_SOFTWARE}.</li>
|
||||
|
||||
<li>{@link android.view.View#LAYER_TYPE_SOFTWARE}: The view is rendered in software into a
|
||||
bitmap.</li>
|
||||
</ul>
|
||||
|
||||
<p>The type of layer you use depends on your goal:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>Performance</strong>: Use a hardware layer type to render a view into a hardware
|
||||
texture. Once a view is rendered into a layer, its drawing code does not have to be executed
|
||||
until the view calls {@link android.view.View#invalidate invalidate()}. Some animations, such as
|
||||
alpha animations, can then be applied directly onto the layer, which is very efficient
|
||||
for the GPU to do.</li>
|
||||
|
||||
<li><strong>Visual effects</strong>: Use a hardware or software layer type and a {@link
|
||||
android.graphics.Paint} to apply special visual treatments to a view. For instance, you can
|
||||
draw a view in black and white using a {@link
|
||||
android.graphics.ColorMatrixColorFilter}.</li>
|
||||
|
||||
<li><strong>Compatibility</strong>: Use a software layer type to force a view to be rendered in
|
||||
software. If a view that is hardware accelerated (for instance, if your whole
|
||||
application is hardware acclerated), is having rendering problems, this is an easy way to work
|
||||
around limitations of the hardware rendering
|
||||
pipeline.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="layers-anims">View layers and animations</h3>
|
||||
|
||||
<p>Hardware layers can deliver faster and smoother animations when your application
|
||||
is hardware accelerated. Running an animation at 60 frames per second is not always possible when
|
||||
animating complex views that issue a lot of drawing operations. This can be alleviated by
|
||||
using hardware layers to render the view to a hardware texture. The hardware texture can
|
||||
then be used to animate the view, eliminating the need for the view to constantly redraw itself
|
||||
when it is being animated. The view is not redrawn unless you change the view's
|
||||
properties, which calls {@link android.view.View#invalidate invalidate()}, or if you call {@link
|
||||
android.view.View#invalidate invalidate()} manually. If you are running an animation in
|
||||
your application and do not obtain the smooth results you want, consider enabling hardware layers on
|
||||
your animated views.</p>
|
||||
|
||||
<p>When a view is backed by a hardware layer, some of its properties are handled by the way the
|
||||
layer is composited on screen. Setting these properties will be efficient because they do not
|
||||
require the view to be invalidated and redrawn. The following list of properties affect the way
|
||||
the layer is composited. Calling the setter for any of these properties results in optimal
|
||||
invalidation and no redrawing of the targeted view:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>alpha</code>: Changes the layer's opacity</li>
|
||||
|
||||
<li><code>x</code>, <code>y</code>, <code>translationX</code>, <code>translationY</code>:
|
||||
Changes the layer's position</li>
|
||||
|
||||
<li><code>scaleX</code>, <code>scaleY</code>: Changes the layer's size</li>
|
||||
|
||||
<li><code>rotation</code>, <code>rotationX</code>, <code>rotationY</code>: Changes the
|
||||
layer's orientation in 3D space</li>
|
||||
|
||||
<li><code>pivotX</code>, <code>pivotY</code>: Changes the layer's transformations origin</li>
|
||||
</ul>
|
||||
|
||||
<p>These properties are the names used when animating a view with an {@link
|
||||
android.animation.ObjectAnimator}. If you want to access these properties, call the appropriate
|
||||
setter or getter. For instance, to modify the alpha property, call {@link
|
||||
android.view.View#setAlpha setAlpha()}. The following code snippet shows the most efficient way
|
||||
to rotate a viewiew in 3D around the Y-axis:</p>
|
||||
<pre>
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
ObjectAnimator.ofFloat(view, "rotationY", 180).start();
|
||||
</pre>
|
||||
|
||||
<p>Because hardware layers consume video memory, it is highly recommended that you enable them
|
||||
only for the duration of the animation and then disable them after the animation is done. You
|
||||
can accomplish this using animation listeners:</p>
|
||||
<pre>
|
||||
View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
view.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
</pre>
|
||||
|
||||
<p>For more information on property animation, see <a href=
|
||||
"{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
|
||||
|
||||
<h2 id="tips">Tips and Tricks</h2>
|
||||
|
||||
<p>Switching to hardware accelerated 2D graphics can instantly increase performance, but you
|
||||
should still design your application to use the GPU effectively by following these
|
||||
recommendations:</p>
|
||||
|
||||
<dl>
|
||||
<dt><strong>Reduce the number of views in your application</strong></dt>
|
||||
|
||||
<dd>The more views the system has to draw, the slower it will be. This applies to the software
|
||||
rendering pipeline as well. Reducing views is one of the easiest ways to optimize your UI.</dd>
|
||||
|
||||
<dt><strong>Avoid overdraw</strong></dt>
|
||||
|
||||
<dd>Do not draw too many layers on top of each other. Remove any views that are completely
|
||||
obscured by other opaque views on top of it. If you need to draw several layers blended on top
|
||||
of each other, consider merging them into a single layer. A good rule of thumb with current
|
||||
hardware is to not draw more than 2.5 times the number of pixels on screen per frame
|
||||
(transparent pixels in a bitmap count!).</dd>
|
||||
|
||||
<dt><strong>Don't create render objects in draw methods</strong></dt>
|
||||
|
||||
<dd>A common mistake is to create a new {@link android.graphics.Paint} or a new {@link
|
||||
android.graphics.Path} every time a rendering method is invoked. This forces the garbage
|
||||
collector to run more often and also bypasses caches and optimizations in the hardware
|
||||
pipeline.</dd>
|
||||
|
||||
<dt><strong>Don't modify shapes too often</strong></dt>
|
||||
|
||||
<dd>Complex shapes, paths, and circles for instance, are rendered using texture masks. Every
|
||||
time you create or modify a path, the hardware pipeline creates a new mask, which can be
|
||||
expensive.</dd>
|
||||
|
||||
<dt><strong>Don't modify bitmaps too often</strong></dt>
|
||||
|
||||
<dd>Every time you change the content of a bitmap, it is uploaded again as a GPU texture the
|
||||
next time you draw it.</dd>
|
||||
|
||||
<dt><strong>Use alpha with care</strong></dt>
|
||||
|
||||
<dd>When you make a view translucent using {@link android.view.View#setAlpha setAlpha()},
|
||||
{@link android.view.animation.AlphaAnimation}, or {@link android.animation.ObjectAnimator}, it
|
||||
is rendered in an off-screen buffer which doubles the required fill-rate. When applying alpha
|
||||
on very large views, consider setting the view's layer type to
|
||||
<code>LAYER_TYPE_HARDWARE</code>.</dd>
|
||||
</dl>
|
||||
@@ -3,208 +3,49 @@ page.title=Graphics
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
<h2>Topics</h2>
|
||||
<ol>
|
||||
<li><a href="#options">Consider your Options</a></li>
|
||||
<li><a href="#draw-to-view">Simple Graphics Inside a View</a></li>
|
||||
<li><a href="#draw-with-canvas">Draw with a Canvas</a>
|
||||
<ol>
|
||||
<li><a href="#on-view">On a View</a></li>
|
||||
<li><a href="#on-surfaceview">On a SurfaceView</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<h2>See also</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/canvas.html">Canvas and Drawables</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware Acceleration</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Android graphics are powered by a custom 2D graphics library, and the framework provides
|
||||
support for high performance 3D graphics in the form of OpenGL ES and RenderScript. The most
|
||||
common 2D graphics APIs can be found in the {@link android.graphics.drawable drawable package}.
|
||||
OpenGL APIs are available from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES} and
|
||||
the {@link android.opengl} packages. The RenderScript APIs are available in the
|
||||
{@link android.renderscript} package.</p>
|
||||
|
||||
<p>When starting a project, it's important to consider exactly what your graphical demands will be.
|
||||
<p>When writing an application, it's important to consider exactly what your graphical demands will be.
|
||||
Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations
|
||||
for a rather static application should be implemented much differently than graphics and animations
|
||||
for an interactive game or 3D rendering.</p>
|
||||
|
||||
<p>Here, we'll discuss a few of the options you have for drawing graphics on Android,
|
||||
and which tasks they're best suited for.</p>
|
||||
|
||||
<p>If you're specifically looking for information on drawing 3D graphics, this page won't
|
||||
help a lot. However, the information below about how to <a href="#draw-with-canvas">Draw with a
|
||||
Canvas</a> (and the section on SurfaceView), will give you a quick idea of how you should draw to
|
||||
the View hierarchy. For more information on Android's 3D graphics APIs, see
|
||||
the <a href="opengl.html">3D with OpenGL</a> and
|
||||
<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> documents.</p>
|
||||
|
||||
|
||||
<h2 id="options">Consider your Options</h2>
|
||||
|
||||
<p>When drawing 2D graphics, you'll typically do so in one of two ways:</p>
|
||||
<ol type="a">
|
||||
<li>Draw your graphics or animations into a View object from your layout. In this manner,
|
||||
the drawing (and any animation) of your graphics is handled by the system's
|
||||
normal View hierarchy drawing process — you simply define the graphics to go inside the View.</li>
|
||||
<li>Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's
|
||||
<code>draw()</code> method (passing it your Canvas), or one of the Canvas <code>draw...()</code> methods (like
|
||||
<code>{@link android.graphics.Canvas#drawPicture(Picture,Rect) drawPicture()}</code>). In doing so, you are also in
|
||||
control of any animation.</li>
|
||||
</ol>
|
||||
|
||||
<p>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 <a href="#draw-to-view">Simple Graphics Inside a View</a>.</li>
|
||||
|
||||
<p>Option "b," drawing to a Canvas, is better when your application needs to regularly re-draw itself.
|
||||
Basically, any video game should be drawing to the Canvas on its own. However, there's more than
|
||||
one way to do this: </p>
|
||||
<ul>
|
||||
<li>In the same thread as your UI Activity, wherein you create a custom View component in
|
||||
your layout, call <code>{@link android.view.View#invalidate()}</code> and then handle the
|
||||
<code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback..</li>
|
||||
<li>Or, in a separate thread, wherein you manage a {@link android.view.SurfaceView} and
|
||||
perform draws to the Canvas as fast as your thread is capable
|
||||
(you do not need to request <code>invalidate()</code>).</li>
|
||||
</ul>
|
||||
<p>...Begin by reading <a href="#draw-with-canvas">Draw with a Canvas</a>.</p>
|
||||
|
||||
<h2 id="draw-to-view">Simple Graphics Inside a View</h2>
|
||||
|
||||
<p>If you'll be drawing some simple graphics (images, shapes, colors, pre-defined animations, etc.),
|
||||
then you should probably just draw to the background of a View or
|
||||
to the content of an {@link android.widget.ImageView} in your layout.
|
||||
In this case, you can skip the rest of this document and learn how to
|
||||
draw graphics and animations in the <a href="2d-graphics.html">2D Graphics</a> document.
|
||||
for an interactive game. Here, we'll discuss a few of the options you have for drawing graphics
|
||||
on Android and which tasks they're best suited for.
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt><strong><a href="{@docRoot}guide/topics/graphics/2d-graphics.html">Canvas and
|
||||
Drawables</a></strong></dt>
|
||||
<dd>Android provides a set of {@link android.view.View} widgets that provide general functionality
|
||||
for a wide array of user interfaces. You can also extend these widgets to modify the way they
|
||||
look or behave. In addition, you can do your own custom 2D rendering using the various drawing
|
||||
methods contained in the {@link android.graphics.Canvas} class or create {@link
|
||||
android.graphics.drawable.Drawable} objects for things such as textured buttons or frame-by-frame
|
||||
animations.</dd>
|
||||
|
||||
<h2 id="draw-with-canvas">Draw with a Canvas</h2>
|
||||
|
||||
<p>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 {@link android.graphics.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 {@link android.graphics.Bitmap}, which is placed into the window.</p>
|
||||
|
||||
<p>In the event that you're drawing within the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code>
|
||||
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 <code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code>,
|
||||
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 {@link android.graphics.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:</p>
|
||||
<pre>
|
||||
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(b);
|
||||
</pre>
|
||||
|
||||
<p>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 <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Matrix,Paint)
|
||||
Canvas.drawBitmap(Bitmap,...)}</code> methods. It's recommended that you ultimately draw your final
|
||||
graphics through a Canvas offered to you
|
||||
by <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code> or
|
||||
<code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code> (see the following sections).</p>
|
||||
|
||||
<p>The {@link android.graphics.Canvas} class has its own set of drawing methods that you can use,
|
||||
like <code>drawBitmap(...)</code>, <code>drawRect(...)</code>, <code>drawText(...)</code>, and many more.
|
||||
Other classes that you might use also have <code>draw()</code> methods. For example, you'll probably
|
||||
have some {@link android.graphics.drawable.Drawable} objects that you want to put on the Canvas. Drawable
|
||||
has its own <code>{@link android.graphics.drawable.Drawable#draw(Canvas) draw()}</code> method
|
||||
that takes your Canvas as an argument.</p>
|
||||
|
||||
|
||||
<h3 id="on-view">On a View</h3>
|
||||
|
||||
<p>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 <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code>.
|
||||
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.</p>
|
||||
|
||||
<p>To start, extend the {@link android.view.View} class (or descendant thereof) and define
|
||||
the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> 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 {@link android.graphics.Canvas}, which is passed to you through the <code>onDraw()</code> callback.</p>
|
||||
|
||||
<p>The Android framework will only call <code>onDraw()</code> as necessary. Each time that
|
||||
your application is prepared to be drawn, you must request your View be invalidated by calling
|
||||
<code>{@link android.view.View#invalidate()}</code>. This indicates that you'd like your View to be drawn and
|
||||
Android will then call your <code>onDraw()</code> method (though is not guaranteed that the callback will
|
||||
be instantaneous). </p>
|
||||
|
||||
<p>Inside your View component's <code>onDraw()</code>, use the Canvas given to you for all your drawing,
|
||||
using various <code>Canvas.draw...()</code> methods, or other class <code>draw()</code> methods that
|
||||
take your Canvas as an argument. Once your <code>onDraw()</code> is complete, the Android framework will
|
||||
use your Canvas to draw a Bitmap handled by the system.</p>
|
||||
|
||||
<p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main
|
||||
Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p>
|
||||
|
||||
<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Custom Components</a>
|
||||
for a guide to extending a View class, and <a href="2d-graphics.html">2D Graphics: Drawables</a> for
|
||||
information on using Drawable objects like images from your resources and other primitive shapes.</p>
|
||||
|
||||
<p>For a sample application, see the Snake game, in the SDK samples folder:
|
||||
<code><your-sdk-directory>/samples/Snake/</code>.</p>
|
||||
|
||||
<h3 id="on-surfaceview">On a SurfaceView</h3>
|
||||
|
||||
<p>The {@link android.view.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.</p>
|
||||
|
||||
<p>To begin, you need to create a new class that extends {@link android.view.SurfaceView}. The class should also
|
||||
implement {@link android.view.SurfaceHolder.Callback}. This subclass is an interface that will notify you
|
||||
with information about the underlying {@link android.view.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.</p>
|
||||
|
||||
<p>Instead of handling the Surface object directly, you should handle it via
|
||||
a {@link android.view.SurfaceHolder}. So, when your SurfaceView is initialized, get the SurfaceHolder by calling
|
||||
<code>{@link android.view.SurfaceView#getHolder()}</code>. You should then notify the SurfaceHolder that you'd
|
||||
like to receive SurfaceHolder callbacks (from {@link android.view.SurfaceHolder.Callback}) by calling
|
||||
{@link android.view.SurfaceHolder#addCallback(SurfaceHolder.Callback) addCallback()}
|
||||
(pass it <var>this</var>). Then override each of the
|
||||
{@link android.view.SurfaceHolder.Callback} methods inside your SurfaceView class.</p>
|
||||
|
||||
<p>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 <code>{@link android.view.SurfaceHolder#lockCanvas() lockCanvas()}</code>.
|
||||
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
|
||||
<code>{@link android.view.SurfaceHolder#unlockCanvasAndPost(Canvas) unlockCanvasAndPost()}</code>, 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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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 <code>{@link android.graphics.Canvas#drawColor(int) drawColor()}</code> or setting a background image
|
||||
with <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Rect,RectF,Paint) drawBitmap()}</code>. Otherwise,
|
||||
you will see traces of the drawings you previously performed.</p>
|
||||
|
||||
|
||||
<p>For a sample application, see the Lunar Lander game, in the SDK samples folder:
|
||||
<code><your-sdk-directory>/samples/LunarLander/</code>. Or,
|
||||
browse the source in the <a href="{@docRoot}guide/samples/index.html">Sample Code</a> section.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><strong><a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware
|
||||
Acceleration</a></strong></dt>
|
||||
<dd>Beginning in Android 3.0, you can hardware accelerate the majority of
|
||||
the drawing done by the Canvas APIs to further increase their performance.</dd>
|
||||
|
||||
<dt><strong><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a></strong></dt>
|
||||
<dd>Android supports OpenGL ES 1.0 and 2.0, with Android framework APIs as well as natively
|
||||
with the Native Development Kit (NDK). Using the framework APIs is desireable when you want to add a
|
||||
few graphical enhancements to your application that are not supported with the Canvas APIs, or if
|
||||
you desire platform independence and don't demand high performance. There is a performance hit in
|
||||
using the framework APIs compared to the NDK, so for many graphic intensive applications such as
|
||||
games, using the NDK is beneficial (It is important to note though that you can still get adequate
|
||||
performance using the framework APIs. For example, the Google Body app is developed entirely
|
||||
using the framework APIs). OpenGL with the NDK is also useful if you have a lot of native
|
||||
code that you want to port over to Android. For more information about using the NDK, read the
|
||||
docs in the <code>docs/</code> directory of the <a href="{@docRoot}sdk/ndk/index.html">NDK
|
||||
download.</a></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
page.title=3D with OpenGL
|
||||
page.title=OpenGL
|
||||
parent.title=Graphics
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
@@ -6,7 +6,7 @@ parent.link=index.html
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
|
||||
|
||||
<ol>
|
||||
<li><a href="#basics">The Basics</a>
|
||||
<ol>
|
||||
@@ -14,7 +14,7 @@ parent.link=index.html
|
||||
</ol>
|
||||
<li><a href="#manifest">Declaring OpenGL Requirements</a></li>
|
||||
</li>
|
||||
<li><a href="#coordinate-mapping">Mapping Coordinates for Drawn Objects</a>
|
||||
<li><a href="#coordinate-mapping">Mapping Coordinates for Drawn Objects</a>
|
||||
<ol>
|
||||
<li><a href="#proj-es1">Projection and camera in ES 1.0</a></li>
|
||||
<li><a href="#proj-es1">Projection and camera in ES 2.0</a></li>
|
||||
@@ -78,8 +78,7 @@ OpenGL ES 2.0 API specification.</p>
|
||||
Kit (NDK). This topic focuses on the Android framework interfaces. For more information about the
|
||||
NDK, see the <a href="{@docRoot}sdk/ndk/index.html">Android NDK</a>.
|
||||
|
||||
<p>
|
||||
There are two foundational classes in the Android framework that let you create and manipulate
|
||||
<p>There are two foundational classes in the Android framework that let you create and manipulate
|
||||
graphics with the OpenGL ES API: {@link android.opengl.GLSurfaceView} and {@link
|
||||
android.opengl.GLSurfaceView.Renderer}. If your goal is to use OpenGL in your Android application,
|
||||
understanding how to implement these classes in an activity should be your first objective.
|
||||
@@ -89,22 +88,22 @@ understanding how to implement these classes in an activity should be your first
|
||||
<dt><strong>{@link android.opengl.GLSurfaceView}</strong></dt>
|
||||
<dd>This class is a {@link android.view.View} where you can draw and manipulate objects using
|
||||
OpenGL API calls and is similar in function to a {@link android.view.SurfaceView}. You can use
|
||||
this class by creating an instance of {@link android.opengl.GLSurfaceView} and adding your
|
||||
this class by creating an instance of {@link android.opengl.GLSurfaceView} and adding your
|
||||
{@link android.opengl.GLSurfaceView.Renderer Renderer} to it. However, if you want to capture
|
||||
touch screen events, you should extend the {@link android.opengl.GLSurfaceView} class to
|
||||
implement the touch listeners, as shown in OpenGL Tutorials for
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html#touch">ES 1.0</a>,
|
||||
implement the touch listeners, as shown in OpenGL Tutorials for
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html#touch">ES 1.0</a>,
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html#touch">ES 2.0</a> and the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity
|
||||
.html">TouchRotateActivity</a> sample.</dd>
|
||||
|
||||
|
||||
<dt><strong>{@link android.opengl.GLSurfaceView.Renderer}</strong></dt>
|
||||
<dd>This interface defines the methods required for drawing graphics in an OpenGL {@link
|
||||
android.opengl.GLSurfaceView}. You must provide an implementation of this interface as a
|
||||
separate class and attach it to your {@link android.opengl.GLSurfaceView} instance using
|
||||
{@link android.opengl.GLSurfaceView#setRenderer(android.opengl.GLSurfaceView.Renderer)
|
||||
GLSurfaceView.setRenderer()}.
|
||||
|
||||
|
||||
<p>The {@link android.opengl.GLSurfaceView.Renderer} interface requires that you implement the
|
||||
following methods:</p>
|
||||
<ul>
|
||||
@@ -129,7 +128,7 @@ href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics
|
||||
android.opengl.GLSurfaceView} geometry changes, including changes in size of the {@link
|
||||
android.opengl.GLSurfaceView} or orientation of the device screen. For example, the system calls
|
||||
this method when the device changes from portrait to landscape orientation. Use this method to
|
||||
respond to changes in the {@link android.opengl.GLSurfaceView} container.
|
||||
respond to changes in the {@link android.opengl.GLSurfaceView} container.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
@@ -173,13 +172,13 @@ interface to OpenGL ES 2.0 and is available starting with Android 2.2 (API Level
|
||||
</ul>
|
||||
|
||||
<p>If you'd like to start building an app with OpenGL right away, have a look at the tutorials for
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html">OpenGL ES 1.0</a> or
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html">OpenGL ES 1.0</a> or
|
||||
<a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html">OpenGL ES 2.0</a>!
|
||||
</p>
|
||||
|
||||
<h2 id="manifest">Declaring OpenGL Requirements</h2>
|
||||
<p>If your application uses OpenGL features that are not available on all devices, you must include
|
||||
these requirements in your <a
|
||||
these requirements in your <a
|
||||
href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a></code> file.
|
||||
Here are the most common OpenGL manifest declarations:</p>
|
||||
|
||||
@@ -200,14 +199,14 @@ shown below.
|
||||
compression formats, you must declare the formats your application supports in your manifest file
|
||||
using <a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
|
||||
<supports-gl-texture>}</a>. For more information about available texture compression
|
||||
formats, see <a href="#textures">Texture compression support</a>.
|
||||
formats, see <a href="#textures">Texture compression support</a>.
|
||||
|
||||
<p>Declaring texture compression requirements in your manifest hides your application from users
|
||||
with devices that do not support at least one of your declared compression types. For more
|
||||
information on how Android Market filtering works for texture compressions, see the <a
|
||||
href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html#market-texture-filtering">
|
||||
Android Market and texture compression filtering</a> section of the {@code
|
||||
<supports-gl-texture>} documentation.</p>
|
||||
<supports-gl-texture>} documentation.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -237,7 +236,7 @@ matrix creates a transformation that renders objects from a specific eye positio
|
||||
<h3 id="proj-es1">Projection and camera view in OpenGL ES 1.0</h3>
|
||||
<p>In the ES 1.0 API, you apply projection and camera view by creating each matrix and then
|
||||
adding them to the OpenGL environment.</p>
|
||||
|
||||
|
||||
<ol>
|
||||
<li><strong>Projection matrix</strong> - Create a projection matrix using the geometry of the
|
||||
device screen in order to recalculate object coordinates so they are drawn with correct proportions.
|
||||
@@ -250,19 +249,19 @@ OpenGL rendering environment.
|
||||
<pre>
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
gl.glViewport(0, 0, width, height);
|
||||
|
||||
|
||||
// make adjustments for screen ratio
|
||||
float ratio = (float) width / height;
|
||||
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
|
||||
gl.glLoadIdentity(); // reset the matrix to its default state
|
||||
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li><strong>Camera transformation matrix</strong> - Once you have adjusted the coordinate system
|
||||
using a projection matrix, you must also apply a camera view. The following example code shows how
|
||||
to modify the {@link
|
||||
to modify the {@link
|
||||
android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.opengles.GL10)
|
||||
onDrawFrame()} method of a {@link android.opengl.GLSurfaceView.Renderer}
|
||||
implementation to apply a model view and use the
|
||||
@@ -276,12 +275,12 @@ which simulates a camera position.
|
||||
// Set GL_MODELVIEW transformation mode
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glLoadIdentity(); // reset the matrix to its default state
|
||||
|
||||
|
||||
// When using GL_MODELVIEW, you must set the camera view
|
||||
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
|
||||
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -294,26 +293,26 @@ tutorial</a>.</p>
|
||||
<p>In the ES 2.0 API, you apply projection and camera view by first adding a matrix member to
|
||||
the vertex shaders of your graphics objects. With this matrix member added, you can then
|
||||
generate and apply projection and camera viewing matrices to your objects.</p>
|
||||
|
||||
|
||||
<ol>
|
||||
<li><strong>Add matrix to vertex shaders</strong> - Create a variable for the view projection matrix
|
||||
and include it as a multiplier of the shader's position. In the following example vertex shader
|
||||
code, the included {@code uMVPMatrix} member allows you to apply projection and camera viewing
|
||||
code, the included {@code uMVPMatrix} member allows you to apply projection and camera viewing
|
||||
matrices to the coordinates of objects that use this shader.
|
||||
|
||||
<pre>
|
||||
private final String vertexShaderCode =
|
||||
|
||||
private final String vertexShaderCode =
|
||||
|
||||
// This matrix member variable provides a hook to manipulate
|
||||
// the coordinates of objects that use this vertex shader
|
||||
"uniform mat4 uMVPMatrix; \n" +
|
||||
|
||||
|
||||
"attribute vec4 vPosition; \n" +
|
||||
"void main(){ \n" +
|
||||
|
||||
|
||||
// the matrix must be included as part of gl_Position
|
||||
" gl_Position = uMVPMatrix * vPosition; \n" +
|
||||
|
||||
|
||||
"} \n";
|
||||
</pre>
|
||||
<p class="note"><strong>Note:</strong> The example above defines a single transformation matrix
|
||||
@@ -340,7 +339,7 @@ variable defined in the vertex shader above.
|
||||
</li>
|
||||
<li><strong>Create projection and camera viewing matrices</strong> - Generate the projection and
|
||||
viewing matrices to be applied the graphic objects. The following example code shows how to modify
|
||||
the {@link
|
||||
the {@link
|
||||
android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10,
|
||||
javax.microedition.khronos.egl.EGLConfig) onSurfaceCreated()} and {@link
|
||||
android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10,
|
||||
@@ -353,16 +352,16 @@ of the device.
|
||||
...
|
||||
// Create a camera view matrix
|
||||
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 unused, int width, int height) {
|
||||
GLES20.glViewport(0, 0, width, height);
|
||||
|
||||
|
||||
float ratio = (float) width / height;
|
||||
|
||||
|
||||
// create a projection matrix from device screen geometry
|
||||
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
@@ -373,16 +372,16 @@ android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.ope
|
||||
onDrawFrame()} method of a {@link android.opengl.GLSurfaceView.Renderer} implementation to combine
|
||||
the projection matrix and camera view created in the code above and then apply it to the graphic
|
||||
objects to be rendered by OpenGL.
|
||||
|
||||
|
||||
<pre>
|
||||
public void onDrawFrame(GL10 unused) {
|
||||
...
|
||||
// Combine the projection and camera view matrices
|
||||
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
|
||||
|
||||
|
||||
// Apply the combined projection and camera view transformations
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
|
||||
|
||||
// Draw objects
|
||||
...
|
||||
}
|
||||
@@ -498,7 +497,7 @@ must run this call on several target devices to determine what compression types
|
||||
supported.</p>
|
||||
</li>
|
||||
<li>Review the output of this method to determine what OpenGL extensions are supported on the
|
||||
device.</li>
|
||||
device.</li>
|
||||
</ol>
|
||||
|
||||
|
||||
@@ -514,7 +513,7 @@ should carefully consider the following factors before starting development with
|
||||
than the ES 1.0/1.1 APIs. However, the performance difference can vary depending on the Android
|
||||
device your OpenGL application is running on, due to differences in the implementation of the OpenGL
|
||||
graphics pipeline.</li>
|
||||
<li><strong>Device Compatibility</strong> - Developers should consider the types of devices,
|
||||
<li><strong>Device Compatibility</strong> - Developers should consider the types of devices,
|
||||
Android versions and the OpenGL ES versions available to their customers. For more information
|
||||
on OpenGL compatibility across devices, see the <a href="#compatibility">OpenGL Versions and Device
|
||||
Compatibility</a> section.</li>
|
||||
@@ -526,7 +525,7 @@ of control by providing a fully programmable pipeline through the use of shaders
|
||||
direct control of the graphics processing pipeline, developers can create effects that would be
|
||||
very difficult to generate using the 1.0/1.1 API.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>While performance, compatibility, convenience, control and other factors may influence your
|
||||
decision, you should pick an OpenGL API version based on what you think provides the best experience
|
||||
for your users.</p>
|
||||
|
||||
Reference in New Issue
Block a user