android--graphics
Graphics
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 Canvas
class or create Drawable
objects for things such as textured buttons or frame-by-frame animations.
docs/
directory of the NDK download.
GLSurfaceView.setRenderer()使其关联到GLSurfaceView
String extensions = javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
Renderscript:
Renderscript提供高性能3D图形和计算,处于native level,使用C99标准,
优点是:
- Portability:可使用在不同处理架构的设备上(CPU, GPU, and DSP for instance) ,It supports all of these architectures without having to target each device, because the code is compiled and cached on the device at runtime.
- Performance:Renderscript provides similar performance to OpenGL with the NDK and also provides a high performance compute API that is not offered by OpenGL.
- Usability:Renderscript simplifies development when possible, such as eliminating JNI glue code and simplifying mesh setup.
- Development complexity:Renderscript introduces a new set of APIs that you have to learn,Renderscript also allocates memory differently compared to OpenGL with the Android framework APIs.
- Debugging visibility: debug难度加大
Renderscript概述:
Renderscript运行在native level,但是仍然需要与android VM通信,因此Renderscript应用程序跟纯VM应用程序不同。Renderscript平台独立。
Renderscript采用C/S结构,底层的Renderscript程序由vm中运行高层的android系统控制。android vm管理内存绑定分配给Renderscript 运行时以供Renderscript程序使用。android framework异步调用renderscript,
在使用renderscropt时,有3个层次的api为renderscript和android framework之间提供通信
android.renderscript
package, allow you to build your application using traditional Android components such as activities and views. When using Renderscript, this layer calls the reflected layer to access the Renderscript runtime.
#include "rs_graphics.rsh"
更多可用函数,请参考 Renderscript runtime API reference。
project_root/gen/package/name/ScriptC_renderscript_filename
的类。这个文件是一个与.rs文件对应的java文件,以供android framework调用。这个类包含以下内容():
project_root/gen/package/name/ScriptField_struct_name的继承自Script.FieldBase的自有类。这个类代表这个结构的数组,这些数组允许为这些结构的实体分配空间。
void touch(float x, float y, float pressure, int id) {if (id >= 10) {return;}touchPos[id].x = x;touchPos[id].y = y;touchPressure[id] = pressure; }
映射成的脚本类:
public void invoke_touch(float x, float y, float pressure, int id) {FieldPacker touch_fp = new FieldPacker(16);touch_fp.addF32(x);touch_fp.addF32(y);touch_fp.addF32(pressure);touch_fp.addI32(id);invoke(mExportFuncIdx_touch, touch_fp); }
函数不能有返回值,因为renderscript系统是异步系统。当android framework调用renderscript时,调用被放到队列中并适时执行。这个限制 This restriction allows the Renderscript system to function without constant interruption and increases efficiency.如果允许函数有返回值,这个调用就会被中断等待返回值。如果renderscript需要传递变量到android framework,使用rsSendToClient()函数。
变量
许多类型可以映射成脚本类,脚本类路径为:project_root/gen/package/name/ScriptC_renderscript_filename,每一个变量都会有一个accessor methods,如在renderscript 代码中声明一个变量,
uint32_t unsignedInteger = 1;
private long mExportVar_unsignedInteger; public void set_unsignedInteger(long v){mExportVar_unsignedInteger = v;setVar(mExportVarIdx_unsignedInteger, v); }public long get_unsignedInteger(){return mExportVar_unsignedInteger; }
typedef struct Point {float2 position;float size; } Point_t;
映射生成的类为: ScriptField_Point.java文件,如下所示:
package com.example.android.rs.hellocompute;import android.renderscript.*; import android.content.res.Resources;/*** @hide*/ public class ScriptField_Point extends android.renderscript.Script.FieldBase {static public class Item {public static final int sizeof = 12;Float2 position;float size;Item() {position = new Float2();}}private Item mItemArray[];private FieldPacker mIOBuffer;public static Element createElement(RenderScript rs) {Element.Builder eb = new Element.Builder(rs);eb.add(Element.F32_2(rs), "position");eb.add(Element.F32(rs), "size");return eb.create();}public ScriptField_Point(RenderScript rs, int count) {mItemArray = null;mIOBuffer = null;mElement = createElement(rs);init(rs, count);}public ScriptField_Point(RenderScript rs, int count, int usages) {mItemArray = null;mIOBuffer = null;mElement = createElement(rs);init(rs, count, usages);}private void copyToArray(Item i, int index) {if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count*/);mIOBuffer.reset(index * Item.sizeof);mIOBuffer.addF32(i.position);mIOBuffer.addF32(i.size);}public void set(Item i, int index, boolean copyNow) {if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];mItemArray[index] = i;if (copyNow) {copyToArray(i, index);mAllocation.setFromFieldPacker(index, mIOBuffer);}}public Item get(int index) {if (mItemArray == null) return null;return mItemArray[index];}public void set_position(int index, Float2 v, boolean copyNow) {if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];if (mItemArray[index] == null) mItemArray[index] = new Item();mItemArray[index].position = v;if (copyNow) {mIOBuffer.reset(index * Item.sizeof);mIOBuffer.addF32(v);FieldPacker fp = new FieldPacker(8);fp.addF32(v);mAllocation.setFromFieldPacker(index, 0, fp);}}public void set_size(int index, float v, boolean copyNow) {if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];if (mItemArray[index] == null) mItemArray[index] = new Item();mItemArray[index].size = v;if (copyNow) {mIOBuffer.reset(index * Item.sizeof + 8);mIOBuffer.addF32(v);FieldPacker fp = new FieldPacker(4);fp.addF32(v);mAllocation.setFromFieldPacker(index, 1, fp);}}public Float2 get_position(int index) {if (mItemArray == null) return null;return mItemArray[index].position;}public float get_size(int index) {if (mItemArray == null) return 0;return mItemArray[index].size;}public void copyAll() {for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);mAllocation.setFromFieldPacker(0, mIOBuffer);}public void resize(int newSize) {if (mItemArray != null) {int oldSize = mItemArray.length;int copySize = Math.min(oldSize, newSize);if (newSize == oldSize) return;Item ni[] = new Item[newSize];System.arraycopy(mItemArray, 0, ni, 0, copySize);mItemArray = ni;}mAllocation.resize(newSize);if (mIOBuffer != null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);} }
产生的这些代码的意义: The generated code is provided to you as a convenience to allocate memory for structs requested by the Renderscript runtime and to interact with struct
s in memory.每个结构的类定义如下的方法的构造函数:
- Overloaded constructors that allow you to allocate memory
- A static nested class,
Item
, allows you to create an instance of thestruct
, in the form of an object. - The
createElement()
method creates a description of the struct in memory. resize()
works much like arealloc()
in C, allowing you to expand previously allocated memory, maintaining the current values that were previously created.copyAll()
synchronizes memory that was set on the framework level to the Renderscript runtime.
typedef struct Point {float2 position;float size; } Point_t;Point_t *touchPoints; int32_t *intPointer;
private ScriptField_Point mExportVar_touchPoints; public void bind_touchPoints(ScriptField_Point v) {mExportVar_touchPoints = v;if (v == null) bindAllocation(null, mExportVarIdx_touchPoints);else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints); }public ScriptField_Point get_touchPoints() {return mExportVar_touchPoints; }private Allocation mExportVar_intPointer; public void bind_intPointer(Allocation v) {mExportVar_intPointer = v;if (v == null) bindAllocation(null, mExportVarIdx_intPointer);else bindAllocation(v, mExportVarIdx_intPointer); }public Allocation get_intPointer() {return mExportVar_intPointer; }
bind_pointer_name(代替set)的特殊方法。这个方法允许绑定由vm分配给renderscript runtime的内存。例如,Working with Allocated Memory
Memory Allocation APIs
array = (int *)malloc(sizeof(int)*10);
Android Object Type | Description |
---|---|
Element
|
An element describes one cell of a memory allocation and can have two forms: basic or complex. A basic element contains a single component of data of any valid Renderscript data type. Examples of basic element data types include a single Complex elements contain a list of basic elements and are created from |
Type
|
A type is a memory allocation template and consists of an element and one or more dimensions. It describes the layout of the memory (basically an array of A type consists of five dimensions: X, Y, Z, LOD (level of detail), and Faces (of a cube map). You can assign the X,Y,Z dimensions to any positive integer value within the constraints of available memory. A single dimension allocation has an X dimension of greater than zero while the Y and Z dimensions are zero to indicate not present. For example, an allocation of x=10, y=1 is considered two dimensional and x=10, y=0 is considered one dimensional. The LOD and Faces dimensions are booleans to indicate present or not present. |
Allocation
|
An allocation provides the memory for applications based on a description of the memory that is represented by a Allocation data is uploaded in one of two primary ways: type checked and type unchecked. For simple arrays there are |
Allocating and binding dynamic memory to the Renderscript
Script.FieldBase
类的构造函数,也可以通过手动创建Allocation。但是更为简单的方法是使用Script.FieldBase 。当申请完内存后,调用reflected layer的bind方法将内存绑定到renderscript runtime。
intPointer
, and a pointer to a struct, touchPoints
. It also binds the memory to the Renderscript:
private RenderScriptGL glRenderer; private ScriptC_example script; private Resources resources;public void init(RenderScriptGL rs, Resources res) {//get the rendering context and resources from the calling methodglRenderer = rs;resources = res;//allocate memory for the struct pointer, calling the constructorScriptField_Point touchPoints = new ScriptField_Point(glRenderer, 2);//Create an element manually and allocate memory for the int pointerintPointer = Allocation.createSized(glRenderer, Element.I32(glRenderer), 2);//create an instance of the Renderscript, pointing it to the bytecode resourcemScript = new ScriptC_example(glRenderer, resources, R.raw.example);//bind the struct and int pointers to the RenderscriptmScript.bind_touchPoints(touchPoints);script.bind_intPointer(intPointer);... }
Reading and writing to memory
rsSendToClient
来克服这个限制。
Reading and writing to global variables
Reading and writing to global variables is a straightforward process. You can use the accessor methods at the Android framework level or set them directly in the Renderscript code. Keep in mind that any changes that you make in your Renderscript code are not propagated back to the Android framework layer.
For example, given the following struct declared in a file named rsfile.rs
:
typedef struct Point {int x;int y; } Point_t;Point_t point;
You can assign values to the struct like this directly in rsfile.rs
. These values are not propagated back to the Android framework level:
point.x = 1; point.y = 1;
You can assign values to the struct at the Android framework layer like this. These values are propagated back to the Renderscript runtime level:
ScriptC_rsfile mScript;...Item i = new ScriptField_Point.Item(); i.x = 1; i.y = 1; mScript.set_point(i);
You can read the values in your Renderscript code like this:
rsDebug("Printing out a Point", point.x, point.y);
You can read the values in the Android framework layer with the following code. Keep in mind that this code only returns a value if one was set at the Android framework level. You will get a null pointer exception if you only set the value at the Renderscript runtime level:
Log.i("TAGNAME", "Printing out a Point: " + mScript.get_point().x + " " + mScript.get_point().y); System.out.println(point.get_x() + " " + point.get_y());
Reading and writing global pointers
Assuming that memory has been allocated in the Android framework level and bound to the Renderscript runtime, you can read and write memory from the Android framework level by using the get
and set
methods for that pointer. In the Renderscript runtime layer, you can read and write to memory with pointers as normal and the changes are propagated back to the Android framework layer, unlike with statically allocated memory.
For example, given the following pointer to a struct
in a file named rsfile.rs
:
typedef struct Point {int x;int y; } Point_t;Point_t *point;
Assuming you already allocated memory at the Android framework layer, you can access values in the struct
as normal. Any changes you make to the struct via its pointer variable are automatically available to the Android framework layer:
point[index].x = 1; point[index].y = 1;
You can read and write values to the pointer at the Android framework layer as well:
ScriptField_Point p = new ScriptField_Point(mRS, 1);Item i = new ScriptField_Point.Item();i.x=100;i.y = 100;p.set(i, 0, true);mScript.bind_point(p);points.get_x(0); //read x and y from index 0points.get_x(0);
Once memory is already bound, you do not have to rebind the memory to the Renderscript runtime every time you make a change to a value。
Compute API用于密集计算,在context of a graphics Renderscript 中使用,比如计算位置,也可以用于脱机计算renderscript,比如图像处理和照片编辑等。
Simple drawing简单的绘图:
RSTextureView
。
rsgDrawRect()
: Sets up a mesh and draws a rectangle to the screen. It uses the top left vertex and bottom right vertex of the rectangle to draw.rsgDrawQuad()
: Sets up a mesh and draws a quadrilateral to the screen.rsgDrawQuadTexCoords()
: Sets up a mesh and draws a quadrilateral to the screen using the provided coordinates of a texture.rsgDrawText()
: Draws specified text to the screen. UsersgFontColor()
to set the color of the text.
Drawing with a mesh:
- Build the mesh with the
Mesh.TriangleMeshBuilder
class, which allows you to specify a set of vertices and indices for each triangle that you want to draw. - Build the mesh using an
Allocation
or a set ofAllocation
s with theMesh.AllocationBuilder
class. This approach allows you to build a mesh with vertices already stored in memory, which allows you to specify the vertices in Renderscript or Android framework code. - Build the mesh with the
Mesh.Builder
class. You should use this convenience method when you know the data types you want to use to build your mesh, but don't want to make separate memory allocations like withMesh.AllocationBuilder
. You can specify the types that you want and this mesh builder automatically creates the memory allocations for you.
Mesh.TriangleMeshBuilder
创建mesh,需要提供构成三角形的顶点和索引。For example, the following code specifies three vertices, which are added to an internal array, indexed in the order they were added. The call to addTriangle()
draws the triangle with vertex 0, 1, and 2 (the vertices are drawn counter-clockwise).
int float2VtxSize = 2; Mesh.TriangleMeshBuilder triangles = new Mesh.TriangleMeshBuilder(renderscriptGL, float2VtxSize, Mesh.TriangleMeshBuilder.COLOR); triangles.addVertex(300.f, 300.f); triangles.addVertex(150.f, 450.f); triangles.addVertex(450.f, 450.f); triangles.addTriangle(0 , 1, 2); Mesh smP = triangle.create(true); script.set_mesh(smP);
Mesh.AllocationBuilder创建mesh,
you need to supply it with one or more allocations that contain the vertex data:
Allocation vertices;... Mesh.AllocationBuilder triangle = new Mesh.AllocationBuilder(mRS); smb.addVertexAllocation(vertices.getAllocation()); smb.addIndexSetType(Mesh.Primitive.TRIANGLE); Mesh smP = smb.create(); script.set_mesh(smP);
In your Renderscript code, draw the built mesh to the screen:
rs_mesh mesh; ...int root(){... rsgDrawMesh(mesh); ... return 0; //specify a non zero, positive integer to specify the frame refresh.//0 refreshes the frame only when the mesh changes. }
Android Object Type | Renderscript Native Type | Description |
---|---|---|
ProgramVertex
|
rs_program_vertex |
The Renderscript vertex program, also known as a vertex shader, describes the stage in the graphics pipeline responsible for manipulating geometric data in a user-defined way. The object is constructed by providing Renderscript with the following data:
Once the program is created, bind it to the The Renderscript runtime then does all the necessary plumbing to send those constants to the graphics hardware. Varying inputs to the shader, such as position, normal, and texture coordinates are matched by name between the input To bind shader constants to the program, declare a The |
ProgramFragment
|
rs_program_fragment |
The Renderscript fragment program, also known as a fragment shader, is responsible for manipulating pixel data in a user-defined way. It's constructed from a GLSL shader string containing the program body, texture inputs, and a To bind shader constructs to the program, declare a The |
ProgramStore
|
rs_program_store | The Renderscript store program contains a set of parameters that control how the graphics hardware writes to the framebuffer. It could be used to enable and disable depth writes and testing, setup various blending modes for effects like transparency and define write masks for color components. |
ProgramRaster
|
rs_program_raster | The Renderscript raster program is primarily used to specify whether point sprites are enabled and to control the culling mode. By default back faces are culled. |
private RenderScriptGL glRenderer; //rendering contextprivate ScriptField_Point mPoints; //verticesprivate ScriptField_VpConsts mVpConsts; //shader constants...ProgramVertex.Builder sb = new ProgramVertex.Builder(glRenderer);String t = "varying vec4 varColor;\n" +"void main() {\n" +" vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +" pos.xy = ATTRIB_position;\n" +" gl_Position = UNI_MVP * pos;\n" +" varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +" gl_PointSize = ATTRIB_size;\n" +"}\n";sb.setShader(t);sb.addConstant(mVpConsts.getType());sb.addInput(mPoints.getElement());ProgramVertex pvs = sb.create();pvs.bindConstants(mVpConsts.getAllocation(), 0);glRenderer.bindProgramVertex(pvs);
The RsRenderStatesRS sample has many examples on how to create a shader without writing GLSL.
Rendering to a Framebuffer Object:渲染到framebuffer对象,framebuffer用在存放即将渲染到屏幕上的数据信息,一个framebuffer对象有两个缓冲区:颜色缓冲区和深度缓冲区。
一般情况下,渲染到framebuffer需要做的事情:
1、为颜色缓冲区和深度缓冲区创建Allocation 对象,然后具体化它们的
USAGE_GRAPHICS_RENDER_TARGET属性,以通知renderscript runtime 的framebuffer对象使用它们。对于颜色缓冲区,必须声明 USAGE_GRAPHICS_TEXTURE
属性来使用颜色缓冲区作为纹理,这是framebuffer对象的常用法。
2、通过调用rsgBindColorTarget来通知renderscript runtime使用渲染到framebuffer对象来代替其默认的framebuffer,同时传递颜色缓冲区Allocation。适当的时候,深度缓冲区也需要这么做,但是需要调用rsgBindDepthTarget而不是rsgBindColorTarget。
3、一般使用rsgDraw函数渲染场景,这些场景会被渲染到颜色缓冲区而不是默认直接显示到屏幕上。
4、当完成第3步的时候,告诉renderscript runtime停止渲染到颜色缓冲区而恢复到渲染默认缓冲区通过调用rsgClearAllRenderTargets。
5、创建片段着色器并将其作为纹理绑定到颜色缓冲区。
6、渲染场景到默认的framebuffer。根据setup片段着色器的方式使用这些纹理。
例子FountainFBO是通过修改Fountain 这个例子来展示如何渲染到framebuffer对象。二者的不同之处是,同样的场景,一个是渲染到默认的framebuffer,一个是渲染到framebuffer对象。
- Modify
fountain.rs
and add the following global variables. This creates setter methods when this file is reflected into a.java
file, allowing you to allocate memory in your Android framework code and binding it to the Renderscript runtime.//allocation for color buffer rs_allocation gColorBuffer; //fragment shader for rendering without a texture (used for rendering to framebuffer object) rs_program_fragment gProgramFragment; //fragment shader for rendering with a texture (used for rendering to default framebuffer) rs_program_fragment gTextureProgramFragment;
- Modify the root function of
fountain.rs
to look like the following code. The modifications are commented:int root() {float dt = min(rsGetDt(), 0.1f);rsgClearColor(0.f, 0.f, 0.f, 1.f);const float height = rsgGetHeight();const int size = rsAllocationGetDimX(rsGetAllocation(point));float dy2 = dt * (10.f);Point_t * p = point;for (int ct=0; ct < size; ct++) {p->delta.y += dy2;p->position += p->delta;if ((p->position.y > height) && (p->delta.y > 0)) {p->delta.y *= -0.3f;}p++;}//Tell Renderscript runtime to render to the frame buffer objectrsgBindColorTarget(gColorBuffer, 0);//Begin rendering on a white backgroundrsgClearColor(1.f, 1.f, 1.f, 1.f);rsgDrawMesh(partMesh);//When done, tell Renderscript runtime to stop rendering to framebuffer objectrsgClearAllRenderTargets();//Bind a new fragment shader that declares the framebuffer object to be used as a texturersgBindProgramFragment(gTextureProgramFragment);//Bind the framebuffer object to the fragment shader at slot 0 as a texturersgBindTexture(gTextureProgramFragment, 0, gColorBuffer);//Draw a quad using the framebuffer object as the texturefloat startX = 10, startY = 10;float s = 256;rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,startX, startY + s, 0, 0, 0,startX + s, startY + s, 0, 1, 0,startX + s, startY, 0, 1, 1);//Rebind the original fragment shader to render as normalrsgBindProgramFragment(gProgramFragment);//Render the main scenersgDrawMesh(partMesh);return 1; }
- In the
FountainRS.java
file, modify theinit()
method to look like the following code. The modifications are commented:/* Add necessary members */ private ScriptC_fountainfbo mScript; private Allocation mColorBuffer; private ProgramFragment mProgramFragment; private ProgramFragment mTextureProgramFragment;public void init(RenderScriptGL rs, Resources res) {mRS = rs;mRes = res;ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);smb.addVertexAllocation(points.getAllocation());smb.addIndexSetType(Mesh.Primitive.POINT);Mesh sm = smb.create();mScript = new ScriptC_fountainfbo(mRS, mRes, R.raw.fountainfbo);mScript.set_partMesh(sm);mScript.bind_point(points);ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);pfb.setVaryingColor(true);mProgramFragment = pfb.create();mScript.set_gProgramFragment(mProgramFragment);/* Second fragment shader to use a texture (framebuffer object) to draw with */pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);/* Set the fragment shader in the Renderscript runtime */mTextureProgramFragment = pfb.create();mScript.set_gTextureProgramFragment(mTextureProgramFragment);/* Create the allocation for the color buffer */Type.Builder colorBuilder = new Type.Builder(mRS, Element.RGBA_8888(mRS));colorBuilder.setX(256).setY(256);mColorBuffer = Allocation.createTyped(mRS, colorBuilder.create(),Allocation.USAGE_GRAPHICS_TEXTURE |Allocation.USAGE_GRAPHICS_RENDER_TARGET);/* Set the allocation in the Renderscript runtime */mScript.set_gColorBuffer(mColorBuffer);mRS.bindRootScript(mScript); }
Note: This sample doesn't use a depth buffer, but the following code shows you how to declare an example depth buffer if you need to use one for your application. The depth buffer must have the same dimensions as the color buffer:
Allocation mDepthBuffer;...Type.Builder b = new Type.Builder(mRS, Element.createPixel(mRS, DataType.UNSIGNED_16,DataKind.PIXEL_DEPTH)); b.setX(256).setY(256); mDepthBuffer = Allocation.createTyped(mRS, b.create(), Allocation.USAGE_GRAPHICS_RENDER_TARGET);
- Run and use the sample. The smaller, white quad on the top-left corner is using the framebuffer object as a texture, which renders the same scene as the main rendering.
android--graphics相关推荐
- Android之android.graphics.drawable.Drawable.Callback回调接口
[java] view plaincopy /*如果你想实现一个扩展子Drawable的动画drawable,那么你可以通过setCallBack(android.graphics.drawable. ...
- Matrix: android 中的Matrix (android.graphics.Matrix) (转)
本篇博客主要讲解一下如何处理对一个Bitmap对象进行处理,包括:缩放.旋转.位移.倾斜等.在最后将以一个简单的Demo来演示图片特效的变换. 1. Matrix概述 对于一个图片变换的处理,需要Ma ...
- android.graphics.drawable.Drawable.Callback回调接口
[java]view plaincopy /*如果你想实现一个扩展子Drawable的动画drawable,那么你可以通过setCallBack(android.graphics.drawable.D ...
- 绘制几何图形——使用android.graphics类 onDraw
范例说明 "如何在和机上绘制2D图形呢?"这是许多android游戏开发都是常提到的问题,在android SDK 当中,并没有Java Graphics2D的函数可以使用,而是使 ...
- android.graphics.bitmap jar,Android入门之画图详解
前文常用的控件介绍了不少,现在就来讨论一下手机开发中常用到的画图.要掌握Android的画图,首先就要了解一下,基本用到的如下一些图形接口: 1.Bitmap,可以来自资源/文件,也可以在程序中创建, ...
- 草根博客[很牛逼的,都浏览下] android Graphics(二):路径及文字
他的博客,都需要浏览下: http://blog.csdn.net/harvic880925?viewmode=contents 前言:今天项目进入攻关期,他们改Bug要改疯掉了,主管为了激励大家,给 ...
- 【Bitmap】Canvas: trying to use a recycled bitmap android.graphics.Bitmap问题
Canvas: trying to use a recycled bitmap android.graphics.Bitmap问题 我这用到bitmap中间变量了,还用到 Bitmap bitmap ...
- boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.Output
log日志 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bit ...
- Android Graphics Tests 程序学习01
转载自:http://zhoujinjian.cc/2018/12/20/Android%20Graphics%20Tests%20%E7%A8%8B%E5%BA%8F%E5%AD%A6%E4%B9% ...
- android绘制图形:android.graphics.drawable.Drawable
android.graphics.drawable 类 Drawable java.lang.Object android.graphics.drawable.Drawable 直接已知子类: Bit ...
最新文章
- OpenGL学习脚印: 投影矩阵和视口变换矩阵
- 【Python】轻松识别文字,这款Python OCR库支持超过80种语言
- 自动化测试工具有哪些_软件测试工程师要具备哪些能力和技能?
- 安装.net5.0后怎么在vs里选择_Visual Stdio 2019(或其它版本)怎样全部安装到非系统盘的实现方法(小白版)...
- Android ThreadUtil 线程公共类,判断是否在主线程/ 子线程执行 相关操作
- 一步步编写操作系统 15 CPU与外设通信——IO接口,下
- 【英语学习】【Level 07】U02 Live Work L4 Welcome to my neighborhood
- asp.net mysql helper_asp.net使用SQLHelper操作数据库
- 怎样用计算机算出圆周率,古代没有计算机的时代 祖冲之是如何算出圆周率的...
- JSP与Servlet 程序设计教程
- dedecms wap模板 html,dedecms医院网站wap模板(橙色)
- 使用Arduino和Node.js实现网页界面控制LED的亮度
- 打开Excel新窗口的方法
- 重装上阵两个人合体机器人_重装上阵多人机甲合体攻略 机甲怎么合体
- 枫叶蓝代码生成工具 和对服装行业的一些感悟
- docker rabbitmq error: touch cannot touch ‘/etc/rabbitmq/rabbitmq.conf‘ permission denied
- iOS: UIScrollView的属性zooming
- 服务器上用U盘安装Linux系统详细步骤
- 面向对象三大特征之多态
- 华为矿鸿操作系统横空出世,煤矿智能化开启新篇章
热门文章
- 【鹅厂手游安全部门电话一面】
- 分解变频电源的原理性
- [SHOI2003]吃豆豆(dp+拓扑排序)
- 《框架设计 CLR Via C# (第2版)》 - 学习笔记
- #009#献给阿尔吉侬的花束
- 重庆那所大学计算机专业最好,重庆哪所大学的计算机专业比较好
- Easy Connect for mac 无法下载
- 欧姆龙CP1H与三菱变频器通讯 CIF01(232串口方式) 欧姆龙CP1H 与变频器modbus 通讯案例
- linux 预览md文件_File Cabinet Pro for mac(菜单栏的文件管理器)
- 44、电子邮件之一(应用层)