2021SC@SDUSC
目录
MSurfaceView类——SurfaceView基本框架
案例——draw_compare
MSurfaceView类——SurfaceView基本框架
重写run()方法
在该方法中,获取开始和结束的时间,如果处于mIsDrawing状态,则调用draw()方法,如果开始和结束时间差<100,则要让线程睡眠到100.
@Override
public void run() {
//获取画布
long start = System.currentTimeMillis();
while (mIsDrawing) {
//画
draw();
}
long end = System.currentTimeMillis();
//解锁画布
if (end - start < 100) {
try {
Thread.sleep(100 - (end - start));
} catch (Exception e) {
e.printStackTrace();
}
}
}
doDraw()方法
private void doDraw(Canvas canvas) {
try {
// mCanvas = mHolder.lockCanvas();
if (canvas != null) {
canvas.drawPath(mPath, mPaint);
}
} catch (Exception e) {
e.printStackTrace();
}
}
drawPath(Path path, Paint paint) 这个方法是通过描述路径的方式来绘制图形的,它的 path 参数就是用来描述图形路径的对象。
draw()方法
private void draw() {
try {
//获得锁
mCanvas = mHolder.lockCanvas();
if (mCanvas != null) {
//画背景
mCanvas.drawBitmap(mBg,null,mDrawPictureRect,null);
// mCanvas.drawColor(Color.WHITE);
//画线
mCanvas.drawPath(mPath, mPaint);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCanvas != null) {
//释放锁
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
abstract Canvas lockCanvas(),获取Surface中的Canvas对象,并锁定之。
draw()方法中先是进行Canvas对象锁的获取,如果Surface中已经有Canvas对象,则进行背景的绘制,在进行画线操作,然后解锁Canvas画布。
surfaceCreate()方法重写
如果处于isDrawing状态,则开启线程。
@Override
public void surfaceCreated(SurfaceHolder arg0) {
mIsDrawing = true;
new Thread(this).start();
}
surfaceDestoryed()方法重写
在销毁时发生,在这里将画面的线程停止、释放。
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
mIsDrawing = false;
}
onSizeChanged()方法重写
该方法进行尺寸改变时的操作
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mDrawPictureRect.set(0, 0, w, h);
}
reset()方法
用于清楚path
public void reset() {
Log.e("TAG","CLEAR");
mPath.reset();
}
getBitmap()方法
public Bitmap getBitmap() {
Log.e("mWidth", "" + mWidth);
Log.e("mHeight", "" + mHeight);
Bitmap bitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
doDraw(canvas);
// canvas.save();
return bitmap;
}
Bitmap.Config有以下几个常量:
public static final Bitmap.Config ALPHA_8 public static final Bitmap.Config ARGB_4444 public static final Bitmap.Config ARGB_8888 public static final Bitmap.Config RGB_565
这些是色彩的存储方法:ARGB
指的是一种 色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue.
其实所有的可见色都是右红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值。
ALPHA_8就是Alpha由8位组成
ARGB_4444就是由4个4位组成即16位
ARGB_8888就是由4个8位组成即32位
RGB_565就是R为5位,G为6位,B为5位共16位
ALPHA_8——代表8位Alpha位图
ARGB_4444——代表16位ARGB位图
ARGB_8888——代表32位ARGB位图
RGB_565——代表8位RGB位图
位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。
changePic()方法
public void changePic(){
reset();
Random random=new Random();
int index=random.nextInt(drawable_list.size());
draw=drawable_list.get(index);
initBitmaps();
}
该方法用于改变背景图。通过random.nextInt(drawable_list.size())生成0~drawable_list.size()(不包括右侧)随机数的方式从drawable_list中选择一个整数,再通过initBitmaps()中调用loadImageByResId(int resId)方法来初始化新的背景图。
private Bitmap loadImageByResId(int resId) {
return BitmapFactory.decodeResource(getResources(), resId);
}
public static Bitmap decodeResource (Resources res, int id, BitmapFactory.Options opts)
- res 包含图像数据的资源对象
- id 图像数据的资源的id
- opts 可以为空,控制采样率和实付图像完全被解码的选项,或者仅仅返回大小
- 返回值
使用Bitmap bm = BitmapFactory.decodeResource(context.getResources(), resId);
通过 bm.getWidth() 和 bm.getHeight() 来获取宽和高;
还有更好的方法:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(context.getResources(), resId, options);
通过 options.outWidth 和 options.outHeight来获取宽和高,这种方法更节省内存。防止oom问题。