1、分析绘图用到的几个类,如Paint、Bitmap、Canvas、Drawable、Rect等
1) Paint
Paint paint = new Paint();
paint.setTextSize(20f);
paint.setColor(Color.argb(255, 255, 0, 0));
paint.setStrokeWidth(2f);
paint.setTextAlign(Align.CENTER);
paint.setStyle(Style.STROKE);
Rect rect = new Rect();
paint.getTextBounds("中国", 0, 2, rect);
paint.ascent();
paint.descent();
2) 自定义Bitmap
Bitmap bitmap = Bitmap.createBitmap(48, 48, Config.ARGB_4444);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
canvas.drawText("hello", 10, 10, paint);
findViewById(R.id.img).setBackgroundDrawable(new BitmapDrawable(getResources(), bitmap));
3)求Bitmap大小
public static float getBitmapSize(Bitmap bitmap){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){//19
return bitmap.getAllocationByteCount()/1024f;
}
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB_MR1){//12
return bitmap.getByteCount()/1024f;
}
return (bitmap.getRowBytes()*bitmap.getHeight())/1024f;
}
2、SurfaceView的使用
1)SurfaceView原理
1)写一个继承SurfaceView的类MySurfaceView
2)写一个继承Thread的线程RenderThread,用于绘制界面
3)写一个实现SurfaceHolder.Callback接口的类MyCallBack
4)在MySurfaceView构造器中获得SurfaceHolder实例,并为其添加MyCallBack回调
5)在surfaceCreated方法里创建并启动RenderThread线程
6)在Activity布局文件里添加MySurfaceView控件
2)事例代码1:
MySurfaceView.java
public class MySurfaceView extends SurfaceView {
private static final String TAG = MySurfaceView.class.getSimpleName();
SurfaceHolder mHolder;
Thread mThread;
Paint mPaint;
Context mContext;
public MySurfaceView(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyle){
super(context,attrs,defStyle);
mContext = context;
init();
Log.d(TAG, "MySurfaceView");
mHolder = getHolder();
mHolder.addCallback(new MyCallBack());
}
private void init(){
mPaint = new Paint();
mPaint.setColor(Color.argb(255, 255, 255, 0));
mPaint.setTextSize(20 * mContext.getResources().getDisplayMetrics().density);
}
private class MyCallBack implements SurfaceHolder.Callback{
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated-"+"width:"+getWidth()+";height:"+getHeight());
mThread = new RenderThread();
mThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//摁home键调用,摁power键不调用
//用华为,联想手机测过
Log.d(TAG, "surfaceDestroyed");
}
}
private class RenderThread extends Thread{
@Override
public void run() {
super.run();
Canvas c = mHolder.lockCanvas();
c.drawText("By the way, how old are you?", 100, 100, mPaint);
mHolder.unlockCanvasAndPost(c);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.qinuli.surfaceviewtest.MySurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
3)事例代码2
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
SurfaceView surfaceView;
SurfaceHolder holder;
//List.get(int)
List<Integer> imgList = new ArrayList<Integer>();
int imgWidth,imgHeight;
//利用LinkedList.removeFirst()
LinkedList<Bitmap> bmList = new LinkedList<Bitmap>();
int imgIndex;
Button btn1;
Button btn2;
//associate handler with looper for current thread
Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button) findViewById(R.id.btn1);
btn2 = (Button) findViewById(R.id.btn2);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview1);
holder = surfaceView.getHolder();
holder.addCallback(new MyCallback());
}
public void onClick(View v){
switch (v.getId()) {
case R.id.btn1:
btn1.setClickable(false);
new LoadAndDrawImage(0, 0).start();
break;
case R.id.btn2:
btn2.setClickable(false);
new LoadImage().start();
new DrawImage(0, imgHeight+10).start();
}
}
class MyCallback implements Callback2{
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.println(Log.INFO, TAG, "surfaceCreated");
Field[] fields = R.drawable.class.getDeclaredFields();
for(Field field:fields){
//prefix,suffix,toLowerCase(),toUpperCase(),toCharArray(),getBytes()
if(field.getName().startsWith("b")){
int index=0;
try {
index = field.getInt(R.drawable.class);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
imgList.add(index);
}
}
Collections.sort(imgList);
Collections.reverse(imgList);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(0));
imgWidth = bitmap.getWidth();
imgHeight = bitmap.getHeight();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.println(Log.INFO, TAG, "surfaceChanged");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.println(Log.INFO, TAG, "surfaceDestroyed");
}
@Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
Log.println(Log.INFO, TAG, "surfaceRedrawNeeded");
}
}
class LoadAndDrawImage extends Thread{
int x,y;
int imgIndex = 0;
public LoadAndDrawImage(int x,int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
super.run();
while(true){
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(imgIndex));
Canvas canvas = holder.lockCanvas(new Rect(x, y, x+imgWidth, y+imgHeight));
canvas.drawBitmap(bitmap, x, y, new Paint());
holder.unlockCanvasAndPost(canvas);
imgIndex++;
if(imgIndex == imgList.size()){
break;
}
}
//跟UI线程交互
handler.post(new Runnable() {
@Override
public void run() {
btn1.setClickable(true);
}
});
}
}
class LoadImage extends Thread{
@Override
public void run() {
super.run();
imgIndex = 0;
while(true){
//从res/drawable加载jpg图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgList.get(imgIndex),null);
bmList.add(bitmap);
imgIndex++;
if(imgIndex == imgList.size()){
break;
}
}
}
}
class DrawImage extends Thread{
int x,y;
public DrawImage(int x,int y){
this.x = x;
this.y = y;
}
@Override
public void run() {
super.run();
while(true){
if(!bmList.isEmpty()){
Canvas canvas = holder.lockCanvas(new Rect(x, y, x+imgWidth, y+imgHeight));
long start = SystemClock.elapsedRealtime();
canvas.drawBitmap(bmList.removeFirst(), x, y, new Paint());
long last = SystemClock.elapsedRealtime()-start;
if(last<100L){
SystemClock.sleep(100L-last);
}
holder.unlockCanvasAndPost(canvas);
}else if(imgIndex == imgList.size()){
break;
}
}
handler.post(new Runnable() {
@Override
public void run() {
btn2.setClickable(true);
}
});
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="单个独立线程"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="两个独立线程"/>
<SurfaceView
android:id="@+id/surfaceview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
