安卓手写板app

最近做的一个课程实验,开发一个可以手写的应用程序,可供用户选择笔迹颜色以及笔迹大小。具体效果如下:


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) {

            }
        });
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值