Android白板方案调研

版权声明:本文为博主原创文章,未经博主允许不得转载。原文链接http://blog.csdn.net/adayabetter?viewmode=contents https://blog.csdn.net/adayabetter/article/details/81034276

Android白板方案调研

代码实现请参看我的另一篇文章 :
Android 白板代码实现

1.参考GitHub开源工程: https://github.com/guanpy/WhiteBoard
2.参考GitHub开源工程: https://github.com/dsbGenius/WhiteBoard
3.主要分析白板的实现方案,以及可以优化的地方。
4.WhiteBoardGenius项目中问题记录:
@1. 横屏时,文字输入框会被软键盘遮挡,而竖屏时则不会被遮挡。
@2. 调研是否支持在图片上进行白板操作。
@3. 已有功能原理理解,新功能预言与添加。
5.主界面为WhiteBoardFragment
6.Canvas介绍:
http://blog.csdn.net/harvic880925/article/details/39080931

画笔功能调研:

1.能够调节画笔粗细
2.能够在白板上使用画笔

新建Test项目:自定义SketchView,实现在白板上使用画笔,效果图如下:
在白板上使用画笔

增加底部操作项菜单:
增加底部操作项菜单

增加画笔弹出框菜单功能项:
弹出框菜单功能项

白板功能整理

1.白板菜单控制及绘画界面为WhiteBoardFragment,界面中黄色框选部分为绘图界面,绿色框选部分为菜单控制界面。 菜单包括:画笔类型、橡皮擦、返回上一步、到下一步、添加图标、添加背景、拖拽模式、保存到本地、删除绘画内容。
绘画界面

2.WhiteBoardFragment

主要逻辑为初始化view,处理底部菜单项点击事件,将相应的参数设置到绘图View中。另外还有画笔类型弹出框、橡皮大小弹出框、文字输入框的处理。

3.代码分析

WhiteBoardFragment继承Fragment,重写其onCreate、onCreateView方法初始化view,并为 view设置监听。
实现onClickListener接口,处理底部菜单点击事件,将参数设置到绘图view中。
实现onDrawChangedListener接口,当绘图View调用onDraw开始绘制时回调该方法,用于处理回退、重置菜单的状态。回退步骤可以通过撤销返回之前的状态,若再次绘制,则撤销状态被清空。
保存图片为耗时操作,使用AsyncTask异步任务保存图片

4.SketchView
绘图View

该类实现主要绘制功能。
onDraw方法实现绘图逻辑,首先drawBackground,绘制背景,若有背景图,则绘制背景图,若无背景图,则绘制白色底板。
然后drawRecord,绘制操作轨迹的内容(如:画笔、橡皮、圆形、图片等),绘制轨迹时,先绘制图片内容,再绘制图片边线、边角图片,最后绘制画笔轨迹(包括:画笔、橡皮、几何图形),所以画笔轨迹始终会在图片的上面。
最后,在onDraw中执行onDrawChangedListener回调,通知出去绘制发生改变。

5.代码分析

SketchView继承View,所以具有View的所有属性,实现onTouchListener接口,对自身设置onTouchListener监听。在onTouch回调中实现所有绘制逻辑。

onTouch方法中的逻辑

@1. 当有2根手指按下,并且间距大于10时,设置actionMode为缩放模式


@2. Action_Down时,执行touch_down逻辑,获取手指按下时的X/Y坐标,判断为画笔模式还是图片模式。

若为画笔模式,则清空之前的RedoList信息,(即下一次编辑开始时,清空之前的RedoList)根据画笔类型(如钢笔、直线、圆、橡皮等)执行相应逻辑,将画笔轨迹信息保存到画笔轨迹List中。
。。。。。。。。
若为图片模式,则先判断手指按下时的X/Y坐标是否在操作图标(如复制、删除、复原、旋转按钮)的范围内,若在范围内,则执行相应逻辑后返回。若不在范围内,则判断是否点击了当前图片,若点击了,则设置actionMode为拖拽模式(Action_Drag),若范围不在当前图片,则判断是否点击了其他图片,若点击了其他图片,则设置该图片为当前选中的图片并设置actionMode为拖拽模式;若点击范围不在其他图片上,则不处理。


@3. Action_Move时,执行touch_move逻辑,preX、preY为上一次的坐标,curX、curY为当前坐标,判断当前模式为画笔模式还是图片模式。
若为画笔模式,根据画笔类型,为钢笔、橡皮时,绘制二次贝塞尔曲线;为直线时,先reset,再设置起点,最后再lineTo到终点;为圆、矩形时,重新设置矩形区域RectF的坐标值,left/top取downX/curX与downY/curY中较小的值,right/botton取较大值。
。。。。。。。。。
若为图片模式,且当curPhotoRecord不为空时执行如下逻辑。
判断actionMode的值: (1)为拖拽模式 Action_Drag,则执行onDragAction,参数为x/y方向上的差值。
(2)为旋转模式 Action_Rotate,则执行onRotateAction,执行旋转加缩放。 (3)为缩放模式
Action_Scale,(两个手指操作),则调用ScaleGestureDetector缩放手势的onTouchEvent执行onScaleAction

注意在onTouch方法中,必须返回true,否则会有异常。

6.问题记录
@1在图片背景上进行橡皮擦操作,会把图片信息擦除掉,而不是仅擦除掉画笔轨迹信息。

问题原因:
绘制时,先绘制的是图片,后绘制画笔轨迹,橡皮擦为白色,所以会把图片信息擦除。


解决思路:
利用canvas分层绘制,最底层是图片背景,中间层是画笔轨迹,最上层是小图片。这样橡皮擦属于中间层,不会擦除底层图片的信息。


方案实施:
参考链接:http://www.eoeandroid.com/thread-43402-1-1.html?_dsign=bcd811c9
1.首先在屏幕上绘制图片背景,如canvas.drawBitmap(bgBitmap,0,0,null);
2.新建Bitmap,再以该Bitmap创建画布,用作橡皮画布,设置画布为透明。
3.画线、画矩形等需要调用橡皮画布的drawPath/drawLine等方法,使用橡皮功能时,设置画笔的颜色为非透明色(为透明则起不到橡皮擦的作用),设置画笔的模式paint.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));最后在橡皮画笔上画出橡皮的路径即可。
4.所有画笔痕迹和橡皮痕迹绘制好后,最后执行
canvas.drawBitmap(tempBitmap,0,0,null),canvas负责将tempBitmap绘制到屏幕上。

问题记录:1. 分析绘制几何图形时的重影问题

在于全夫同学的帮忙下,找到
出现重影问题的原因:由于绘制采用分层思想,底层是图片层,上层是画笔
轨迹层,画笔轨迹是new的 canvas,在bitmap上绘制轨迹,每次touch move事件触发绘制,
bitmap上的轨迹未做清空操作,导致之前的画笔轨迹始终会在屏幕上。
解决方案:手指在做touch move时,绘制下一位置的图形时,先清空之前位置的图形信息,
如此,既能实现几何图形跟随手指移动,也解决了重影的问题

最终效果图如下图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/adayabetter/article/details/81034276