Android Bitmap Paint 绘图范例
前面我们学习了 Bitmap 和一些基本的绘图 API 的属性以及常用的方法,这章节我们就写个 demo 来练练手
简单画图板
这个相信大家都不陌生,很多手机都会自带一个给用户涂鸦的画图板,这里我们就简易的实现一个
思路
-
画图需要一直画笔 ( Paint ),一块画布( Canvas) ,一个路径 (Path) 记录用户绘制的路线
-
为了将画布 (Canvas) 显示到屏幕上,我们需要自定义一个
View
,重写onDraw()
方法完成画图,因为要跟随手指移动的轨迹,所以要重写onTouchEvent()
方法获取手势 -
还有一点,划线的时候,每次都是从上次拖动时间的发生点到本次拖动时间的发生点,那么之前绘制的 就会丢失,为了保存之前绘制的内容,我们可以引入所谓的 "双缓冲" 技术
也就是每次不是直接绘制到
Canvas
上,而是先绘制到Bitmap
上,等Bitmap
上的绘制完了,再一次性地绘制到View
具体实现
- 初始化画笔,设置颜色等等一些参数
- 在
View
的onMeasure()
方法中创建一个View
大小的Bitmap
,同时创建一个Canvas
onTouchEvent()
中获得X,Y
坐标,做绘制连线,最后invalidate()
重绘
范例
-
创建一个 空的 Android 项目
cn.twle.android.BitmapPaint
-
自定义一个 View 类
MsView.java
package cn.twle.android.bitmappaint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class MsView extends View{ private Paint mPaint; //绘制线条的 Path private Path mPath; //记录用户绘制的 Path private Canvas mCanvas; //内存中创建的 Canvas private Bitmap mBitmap; //缓存绘制的内容 private int mLastX; private int mLastY; public MsView(Context context) { super(context); init(); } public MsView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ mPath = new Path(); mPaint = new Paint(); //初始化画笔 mPaint.setColor(Color.GREEN); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); //结合处为圆角 mPaint.setStrokeCap(Paint.Cap.ROUND); // 设置转弯处为圆角 mPaint.setStrokeWidth(20); // 设置画笔宽度 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); // 初始化bitmap,Canvas mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } //重写该方法,在这里绘图 @Override protected void onDraw(Canvas canvas) { drawPath(); canvas.drawBitmap(mBitmap, 0, 0, null); } //绘制线条 private void drawPath(){ mCanvas.drawPath(mPath, mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE: int dx = Math.abs(x - mLastX); int dy = Math.abs(y - mLastY); if (dx > 3 || dy > 3) mPath.lineTo(x, y); mLastX = x; mLastY = y; break; } invalidate(); return true; } }
-
修改
MainActivity.java
设置setContentView(new MsView(MainActivity.this))
package cn.twle.android.bitmappaint; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MsView(MainActivity.this)); } }