最近做的一个课程实验,开发一个可以手写的应用程序,可供用户选择笔迹颜色以及笔迹大小。具体效果如下:
1)在XML文件中定义RadioGroup、RadioButton,SeekBar以及自定义View——WritingView。具体布局就不介绍了,后面直接给出代码。
2)在自定义View中实现手写功能:首先由于View中的onDraw方法每次绘制时都会把非当前轨迹清除,所以需要另外定义一个画布进行保存。这里定义Canvas和Bitmap。具体实现如下:
private Canvas mCanvas; //定义画布 private Bitmap mBitmap;
public WritingView(Context context, AttributeSet attrs) {super(context, attrs);mCanvas = new Canvas(); }@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);mCanvas.setBitmap(mBitmap); }@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(mBitmap,0,0,null); }然后重写onTouchEvent方法,实现当手指在屏幕上移动时,会把手指移动轨迹画出来。private float startX; //手写起点 private float startY;public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:startX = event.getX();//将手接触屏幕时的位置设为起点 startY = event.getY();break;case MotionEvent.ACTION_MOVE:mCanvas.drawLine(startX,startY,event.getX(),event.getY(),paint);//画起点到移动点间的线 postInvalidate();//视图刷新 startX = event.getX();//重改起点,这样才能绘制出随着手移动的曲线来 startY = event.getY();break;case MotionEvent.ACTION_UP:mCanvas.drawLine(startX,startY,event.getX(),event.getY(),paint);postInvalidate();break;default:break;}return true; }其中在移动过程中,画线结束后要改变起点位置,这样才能得到由一段段线段组成的曲线。3)在自定义View中定义setColor和setPaintSize方法,用于在MainActivity中调用。这样就完成了手写板的功能。下面给出MainActivity和WritingView的完整代码:WritingView代码:public class WritingView extends View {Paint paint = new Paint(); //定义画笔 private Canvas mCanvas; //定义画布 private Bitmap mBitmap;private float startX; //手写起点 private float startY;public WritingView(Context context, AttributeSet attrs) {super(context, attrs);mCanvas = new Canvas();}@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);mCanvas.setBitmap(mBitmap);}@Override public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:startX = event.getX();//将手接触屏幕时的位置设为起点 startY = event.getY();break;case MotionEvent.ACTION_MOVE:mCanvas.drawLine(startX,startY,event.getX(),event.getY(),paint);//画起点到移动点间的线 postInvalidate();//视图刷新 startX = event.getX();//重改起点,这样才能绘制出随着手移动的曲线来 startY = event.getY();break;case MotionEvent.ACTION_UP:mCanvas.drawLine(startX,startY,event.getX(),event.getY(),paint);postInvalidate();break;default:break;}return true;}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(mBitmap,0,0,null);}//改变画笔颜色的方法 public void setColor(int color){if (paint!=null){paint.setColor(color);}}//改变画笔大小的方法 public void setPaintSize(float size){if (paint!=null){paint.setStrokeWidth(size);}} }MainActivity代码:import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.SeekBar;public class MainActivity extends AppCompatActivity {WritingView writingView;private RadioGroup radioGroup;private SeekBar seekBar;@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);writingView = (WritingView) findViewById(R.id.writing);radioGroup = (RadioGroup) findViewById(R.id.color_group);seekBar = (SeekBar) findViewById(R.id.paint_size);writingView.setColor(getResources().getColor(R.color.colorBlue));//设置默认情况下字体颜色为蓝色 writingView.setPaintSize(20);//设置默认情况下字体大小为20 radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Override public void onCheckedChanged(RadioGroup group, int checkedId) {//根据选择不同的radioButton项,调用writingView中的setColor方法改变画笔颜色 switch (checkedId){case R.id.black:writingView.setColor(getResources().getColor(R.color.colorBlack));break;case R.id.red:writingView.setColor(getResources().getColor(R.color.colorRed));break;case R.id.green:writingView.setColor(getResources().getColor(R.color.colorGreen));break;case R.id.blue:writingView.setColor(getResources().getColor(R.color.colorBlue));break;default:break;}}});final int seekBarMax = seekBar.getMax();//获取用于改变画笔大小的seekBar的最大值,目的是便于将seekBar值转换成百分数 seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {writingView.setPaintSize((float)progress*20/seekBarMax);//将seekBar的进度值转换成百分数并乘以倍数,实现改变画笔大小 }@Override public void onStartTrackingTouch(SeekBar seekBar) {}@Override public void onStopTrackingTouch(SeekBar seekBar) {}});} }