一、 android.graphics.Matrix
有关图形的变换、缩放等相关操作常用的方法有:
void reset() // 重置一个matrix对象。
void set(Matrix src) //复制一个源矩阵,和本类的构造方法 Matrix(Matrix src) 一样
boolean isIdentity() //返回这个矩阵是否定义(已经有意义)
void setRotate(float degrees) //指定一个角度以0,0为坐标进行旋转
void setRotate(float degrees, float px, float py) //指定一个角度以px,py为坐标进行旋转
void setScale(float sx, float sy) // 缩放
void setScale(float sx, float sy, float px, float py) //以坐标px,py进行缩放
void setTranslate(float dx, float dy) //平移
void setSkew (float kx, float ky, float px, float py) //以坐标px,py进行倾斜
void setSkew (float kx, float ky) //倾斜
二、android.graphics.NinePatch
NinePatch是Android平台特有的一种非矢量图形自然拉伸处理方法,可以帮助常规的图形在拉伸时不会缩放,实例中Android开发网提示大家对于Toast的显示就是该原理,同时SDK中提供了一个工具名为Draw 9-Patch,有关该工具的使用方法可以参考我们经发布的 Draw 9-Patch使用方法介绍一文。由于该类提供了高质量支持透明的缩放方式,所以图形格式为PNG,文件命名方式为.9.png 的后缀比如android123.9.png。
三、android.graphics.Paint
Paint类我们可以理解为画笔、画刷的属性定义,本类常用的方法如下:
void reset() //重置
void setARGB(int a, int r, int g, int b) 或 void setColor(int color) 均为设置Paint对象的颜色
void setAntiAlias(boolean aa) //是否抗锯齿,需要配合void setFlags (Paint.ANTI_ALIAS_FLAG) 来帮助消除锯齿使其边缘更平滑。
Shader setShader(Shader shader) //设置阴影,Shader类是一个矩阵对象,如果为NULL将清除阴影。
void setStyle(Paint.Style style) //设置样式,一般为 FILL 填充,或者STROKE凹陷效果。
void setTextSize(float textSize) //设置字体大小
void setTextAlign(Paint.Align align) //文本对齐方式
Typeface setTypeface(Typeface typeface) //设置字体,通过Typeface可以加载Android内部的字体,一般为宋体对于中文,部分ROM可以自己添加比如雅黑等等
void setUnderlineText(boolean underlineText) //是否设置下划线,需要撇和void setFlags (Paint.UNDERLINE_TEXT_FLAG) 方法。
四、android.graphics.Rect
Rect我们可以理解为矩形区域,类似的还有Point一个点,Rect类除了表示一个矩形区域位置描述外,android123提示主要可以帮助我们计算图形之间是否碰撞(包含)关系,对于Android游戏开发比较有用,其主要的成员contains包含了三种重载方法,来判断包含关系
boolean contains(int left, int top, int right, int bottom)
boolean contains(int x, int y)
boolean contains(Rect r)
五、android.graphics.Region
Region在Android平台中表示一个区域和Rect不同的是,它表示的是一个不规则的样子,可以是椭圆、多边形等等,而Rect仅仅是矩形。同样Region的boolean contains(int x, int y) 成员可以判断一个点是否在该区域内
六、android.graphics.Typeface
Typeface类是帮助描述一个字体对象,在TextView中通过使用setTypeface方法来制定一个输出文本的字体,其直接构造调用成员create方法可以直接指定一个字体名称和样式,比如
static Typeface create(Typeface family, int style)
static Typeface create(String familyName, int style)
同时使用isBold和isItalic方法可以判断出是否包含粗体或斜体的字型。
final boolean isBold()
final boolean isItalic()
该类的创建方法还有从apk的资源或从一个具体的文件路径,其具体方法为
static Typeface createFromAsset(AssetManager mgr, String path)
static Typeface createFromFile(File path)
static Typeface createFromFile(String path)
SurfaceView简单例子
作者:Legend
QQ:158067568
上一节讨论了SurfaceView的初步知识,这一节将通过一个简单的例子来进一步学习SurfaceView。
本节将学习一个例子来对上一节内容做个总结,该例子讲演示一个篮球上下运动的动画。java eye的blog贴图还需要将图片上传到其他网站在转帖,我实在觉得有些麻烦,所以就不贴图了。大家下载之后再机子上运行一下就ok了。
实现Activity中很简单,代码中需要注意的地方与知识点都已经给了注释,代码如下:
package cn.edu.heut.zcl; import android.app.Activity; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Window; import android.view.WindowManager; public class SportActivity extends Activity { public int screenWidth ; public int screenHeight ; BallSurfaceView bsv ; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); bsv = new BallSurfaceView(this); //获得屏幕尺寸 DisplayMetrics dm = new DisplayMetrics(); dm = this.getApplicationContext().getResources().getDisplayMetrics(); screenWidth = dm.widthPixels; screenHeight = dm.heightPixels; //下两句为设置全屏 requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(bsv); } }
接下来介绍球类:
package cn.edu.heut.zcl; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.DisplayMetrics; /** * 球类 * @author zcl * */ public class Ball { /** * 球的高 */ public static final int HEIGHT = 93; /** * 球的宽 */ public static final int WIDTH = 93; private static final int STEPLENGTH = 10;//每次运动的间距 private static final float REDUCEPERCENTAGE = 0.35F;//递减系数 private int stepReduce ;//每次反向运动的缩短的距离 private float runX ;//球的位置 private float runY ;//球的位置 private BallSurfaceView bsv ; private boolean upDirection = false;//if true,up direction,or is down direction private float maxHeight ;//当前运动最高的高度 private Paint paint ; Bitmap ballBitmap ;//球的图片 SportActivity sa ; public Ball(float initX , float initY , BallSurfaceView bsv){ this.runX = initX; this.runY = initY ; maxHeight = initY; this.bsv = bsv; ballBitmap = BitmapFactory.decodeResource(bsv.getResources(), R.drawable.ball);//加载图片 paint = new Paint(); sa = bsv.sportActivity; } public void onDraw(Canvas canvas) { int c = paint.getColor();//保存颜色,之后还原为之前颜色 boundaryTest(); if(canvas != null) canvas.drawBitmap(ballBitmap,runX,runY,paint); paint.setColor(c); move(); } /** * 运动 */ private void move() { if(maxHeight >= (sa.screenHeight - HEIGHT)) { return; } if(upDirection){//向上 runY = runY + STEPLENGTH ; }else{ runY = runY - STEPLENGTH ; } } /** * 边界检测,使球不会飞出边界 */ private void boundaryTest(){ if(runY > sa.screenHeight - HEIGHT){//向下运动到头 upDirection = !upDirection;//方向置反 runY = sa.screenHeight - HEIGHT; stepReduce = (int) (maxHeight * REDUCEPERCENTAGE); maxHeight = maxHeight + stepReduce ;//最大高度递减 } if(runY < maxHeight ){//向上运动到头 upDirection = !upDirection;//方向置反 if(maxHeight >= (sa.screenHeight - HEIGHT)) return; runY = maxHeight ; } } }
SurfaceView类:
package cn.edu.heut.zcl; import android.R.color; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.SurfaceHolder; import android.view.SurfaceView; public class BallSurfaceView extends SurfaceView implements SurfaceHolder.Callback{ SportActivity sportActivity ;//调用该SurfaceView的上下文引用 private Ball ball ;//小球 SurfaceHolder holder ; public BallSurfaceView(Context context) { super(context); this.sportActivity = (SportActivity)context ; ball = new Ball(100, 100, this); holder = this.getHolder(); holder.addCallback(this); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(canvas == null) canvas = holder.lockCanvas();//锁定画布 Paint p = new Paint(); int c = p.getColor(); p.setColor(Color.WHITE);//设置背景白色 if(canvas != null) canvas.drawRect(0, 0, sportActivity.screenWidth, sportActivity.screenHeight, p); p.setColor(c); ball.onDraw(canvas); holder.unlockCanvasAndPost(canvas);//释放锁 } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { new RefreshThread().start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } private class RefreshThread extends Thread{ @Override public void run() { while(true){ Canvas canvas = null; try{ onDraw(canvas); }catch(Exception e){ e.printStackTrace(); } try { Thread.sleep(40); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
代码中的注释已经很清楚了,具体原理参考上一节的内容。如需代码,留下邮箱。
运行了一下,基本明白了。 谢谢!
谢谢分享!
Android----Thread+Handler 线程 消息循环( 转载)
近来找了一些关于android
线程间通信的资料,整理学习了一下,并制作了一个简单的例子。
andriod
提供了 Handler
和 Looper
来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler
来传递的。
在 Android
,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper
,这个事android
的新 概念。我们的主线程(UI
线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handle
,我们有消息循环,就要往消息循环里
面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,消息的的处理,把这些都封装在Handle
里面,注意Handle
只是针对那 些有Looper
的线程,不管是UI
线程还是子线程,只要你有Looper
,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI
相关的东西,就不能放在子线程中,因为子线程是不能操作UI
的,只能进行数据、系统等其他非UI
的操作。
在Android
,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper
,这个是android
的新概 念。我们的主线程(UI
线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handler
,我们有消息循环,就要往消息循环里
面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,把这些都封装在Handler
里面,注意Handler
只是针对那 些有Looper
的线程,不管是UI
线程还是子线程,只要你有Looper
,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI
相关的东西,就不能放在子线程中,因为子线程是不能操作UI
的,只能进行数据、系统等其他非UI
的操作。
一个Handler
的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler
之前先初始化线程的消息队列。如下面的代码:
Java 代码
class ChildThread extends Thread {
public void run() {
/*
* 创建 handler 前先初始化Looper.
*/
Looper.prepare();
/*
* 在子线程创建handler ,所以会绑定到子线程的消息队列中
*
*/
mChildHandler = new Handler() {
public void handleMessage(Message msg) {
/*
* Do some expensive operations there.
*/
}
};
/*
* 启动该线程的消息队列
*/
Looper.loop();
}
}
当Handler
收到消息后,就会运行handleMessage(…)
的回调函数,可以在里面做一些耗时的操作。
最后完成了操作要结束子线程时,记得调用quit()
来结束消息循环队列。
mChildHandler.getLooper().quit();
下面是一个线程间通信的小例子:
Java 代码