Android实现自定义RelativeLayout可拖动、缩放、旋转TextView

loisonly 7年前
   <p>因最近公司项目需求,需要做出一个在一张背景图上添加文字,文字可编辑如修改颜色、样式、字体、背景添加气泡等,也可对文字的位置进行修改,实现拖动、旋转、缩放等功能,类似于美图秀秀中文字的添加,最后可将背景图和文字联合生成一张图片,保存到相册中,在网上也没有找到合适的代码以供参考,所以决定自己写一个自定义的控件实现以上的效果。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/bb5a7573efd01bf8ebf5fdd5f1789096.gif"></p>    <p>先贴上图看一下效果,这个demo的基本功能包括:</p>    <p>一、点击自定义View可以创建标签,点击标签滑动可以改变标签位置;</p>    <p>二、在View上进行两指缩放旋转可以改变标签的方向和大小,当有多个标签TextView存在时,两指缩放和旋转会自动寻找离两指中心点最近的TextView标签进行操作</p>    <p>三、在自定义上可识别左滑和右滑操作!</p>    <p>四、可监控TextView的实时滑动!</p>    <p>五、对话框中可滑动滑条改变字体颜色!</p>    <p>六、点击保存能将画布生成图片保存下来!</p>    <p>实现这个效果的基本思路如下:</p>    <p>首先,我们自定义一个MyView继承RelativeLayout,然后对该MyRelativeLayout进行onTouchEvent的事件进行监听,以此来判断是什么事件,对于父布局,我们需要分类的事件有单击事件,左右滑动事件,两个手指的缩放,旋转操作,对于最后操作的TextView,我们需要监听的事件有单击事件,两个手指的缩放和旋转操作。</p>    <p>对于MyView,单击事件就是单纯的点击事件,他是用来触发产生新的TextView的事件来源,也就是点击MyView就会生成新的标签,还有左右滑动事件,因为在公司的项目中还需要添加滤镜的效果,所以我们要监听左右滑动的事件来实现切换上下两种不同的滤镜效果,然后通过借口回调的的方式告诉调用者即可!最后就是两个手指的滑动事件,我们要通过两个手指在移动过程中两个手指之间的距离的渐变来判断当前用户是想实现放大还是缩小的功能,同时,根据刚开始的两个手指的落点的连线和滑动过程中两个手指的连线来确定用户的旋转角度,从而改变标签TextView的旋转角度。</p>    <p>对于标签TextView本身,点击事件是为了确定我门当前操作的焦点是在哪个TextView上,因为到时候MyView上有很多个标签TextView,我门会把所有的TextView保存到List之中去,然而每次操作的只有一个全局的TextView所以我们每次在点击一个TextView的时候就要把被点击的TextView赋值给全局的TextView,代表我们操作的是哪一个View,然后当我们按住TextView滑动的时候,实现的效果是在MyView上的移动效果,当我们两个手指在TextVIew上的时候,TextView本身也要监听是否有旋转和缩放,从而改变TextView自己的旋转角度和缩放效果。</p>    <p>首先,我们对MyView进行分析。当然稍后我会给出整个自定义控件的所有代码。</p>    <p>我们需要关注的是MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP,MotionEvent.ACTION_POINTER_UP,MotionEvent.ACTION_POINTER_DOWN,MotionEvent.ACTION_CANCEL.</p>    <p>首先,我们讨论在MyView上滑动实现对TextView的缩放和旋转操作。当我们有两个以上的手指触摸view的时候,菜具备触发缩放和旋转的条件,此时,我们需要监听ACTION_DOWN和ACTION_POINTER_DOWN,如果两个事件同时触发,说明有两个手指,此时我们纪录下刚落点时的两个点的坐标,然后在两个手指的滑动过程中,我们在ACTINON_MOVE事件中去动态的获取滑动中的两个点的坐标,然后实时的去计算两个点之间的距离,再与之前的距离进行比较,如果比之前的打大,说明用户的意图是放大,反之就是缩小,于此同时,计算两个点之间的连线与之前两个点之间点连线的角度,再根据整个计算出来的角度对TextView进行旋转操作。</p>    <p>由于为了提高用户的体验,我们决定当MyView上有很多标签TextView的时候,在MyView上进行缩放和旋转操作的时候,我们会自动的去计算两个手指之间的中点坐标,然后去遍历List中存储的所有TextView的位置信息,去匹配List中所有TextView的中心与两个手指中点最近的TextView,对它进行操纵,这样,用户就不用专门去找到某一个TextView去点击一个它才能对他操作了,提高用户体验度,尤其是操作某一个TextView非常小的时候,手指压根点不到的时候。</p>    <p>另外,在TextView上的操作,原理都一样,在这里就不再赘述,稍后给出的代码中也有相应的注释,相信一看便知,大家在测试的时候直接将该自定义View使用到布局文件中即可,就可以测试其功能,项目还没有上线,所以说该自定义控件可能还有bug没有修改,希望大家一起改正,谢谢。</p>    <p> </p>    <p> </p>