最近做的一个课程实验,开发一个可以手写的应用程序,可供用户选择笔迹颜色以及笔迹大小。具体效果如下:
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) { } }); } }