TextureView
SurfaceView和TextureView 两者都能在独立的线程中绘制和渲染,在专用的GPU线程中大大提高渲染的性能。
SurfaceView可以通过SurfaceHolder.addCallback方法在子线程中更新UI
TextureView则可以通过TextureView.setSurfaceTextureListener在子线程中更新UI
Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用。
TextureView和其它普通View一样进行移动,旋转,缩放,动画等变化。
TextureView只能在开启了硬件加速的Window中使用,并且消费的内存要比SurfaceView多,并伴随着1-3帧的延迟。
每秒1帧随机字符串显示在屏幕中间。
package com.zhangyu.surfaceplayer;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
import android.util.AttributeSet;
import android.util.Log;
import android.view.TextureView;
import java.util.Random;
/**
* TextureView的基本用法。
*/
public class MyTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private static final String TAG = "MyTextureView";
private Thread thread;//用于绘制的线程
private boolean isRunning;//线程的控制开关
private Canvas canvas;
private Paint paint;
private int fps = 1;
public MyTextureView(Context context) {
this(context, null);
}
public MyTextureView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setSurfaceTextureListener(this);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.GREEN);
paint.setTextSize(50);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
isRunning = true;
thread = new Thread(new Runnable() {
@Override
public void run() {
//不断绘制
while (isRunning) {
long startMs = System.currentTimeMillis();
draw();
long endMs = System.currentTimeMillis();
long needTime = 1000 / fps;
long usedTime = endMs - startMs;
if (usedTime < needTime) {
try {
Thread.sleep(needTime - usedTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
thread.start();
}
private void draw() {
//View被销毁,但是子线程可能还在进行操作,可能抛出一些异常
try {
canvas = lockCanvas();
//按home或者back,SurfaceView被销毁,所以需要判空canvas
if (canvas != null) {
//todo 开始绘制
//黑色清屏
canvas.drawColor(Color.BLACK);
drawTextWithCenterPoint(canvas, getWidth() / 2, getHeight() / 2, getRandomString(10), paint);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
unlockCanvasAndPost(canvas);
}
}
}
/**
* 获取一条随机字符串
* @param length
* @return
*/
public String getRandomString(int length) { //length表示生成字符串的长度
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
Log.e(TAG, "getRandomString: " + sb.toString());
return sb.toString();
}
/**
* 以中心点绘制文字
*
* @param canvas
* @param centerX
* @param centerY
* @param text
* @param paint
*/
private void drawTextWithCenterPoint(Canvas canvas, int centerX, int centerY, String text, Paint paint) {
//获取文本的宽度,但是是一个比较粗略的结果
float textWidth = paint.measureText(text);
//文字度量
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
//得到基线的位置
float baselineY = centerY + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
//绘制
canvas.drawText(text, centerX - textWidth / 2, baselineY, paint);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
isRunning = false;
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}