Android开源:DragerViewLayout-可拖拽,移动,自由组合子控件的视图控件

KatJudkins 7年前
   <p>今天给大家推荐一个自由拖拽,自由组合的控件,这个控件是我自定义写的。通过它,我们可以自由拖拽,自由组合实现一个界面,满足一个用户自由组合界面的需求。这里不是通过自由拖拽控件,来快速开发一个界面,而且更人性化的让用户去自由组合一个界面。</p>    <h2>前言</h2>    <p>最近有一个项目,有一个主界面,界面上有很多控件或者有多个 fragment 组成,大小不一,而且由于用户需要,需要自由拖动和自由组合,形成用户自己需要的组合成的模样。所以就写了一个 DragerViewLayout ,只要在 DragerViewLayout 下,写入了多个视图,就可以自由拖动和组合了。DragerViewLayout 本质上是一个相对布局,所以初始位置都可以自己按相对布局的方式来定义,然后用户手动拖动后,会自动记录每个子视图的位置,进行保存,等到重新加载后,会按照记录的位置进行布局。</p>    <h2>效果图</h2>    <p>说一千道一万,不如看实践,那就一起来欣赏一下效果图的效果如何吧?</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/eaa53ef342876972f714c026f6b4df05.gif"> <img src="https://simg.open-open.com/show/502057786ea137646ff8888c1bd3e0cc.gif"></p>    <p>你们感觉如何?</p>    <h2>实现思路</h2>    <h3>首先</h3>    <p>首先,我们来想想,要是实现各个子控件和视图之间的拖拽和交换位置,那这就意味着所有的子视图和控件必须在一个层级之内,否则跨层级的拖拽是非常难实现的。所以第一个思路就是:</p>    <p>使用相对布局</p>    <p>使用相对布局,其实可以满足所有控件都在一个层级之内的,而且可以满足我们初始的任何样式的布局。况且相对布局是 Android 官方推荐使用的布局。</p>    <h3>其次</h3>    <p>其次,就该讨论拖拽的问题了,如何实现拖拽呢?有没有更好的,简单的方式呢?难道只能自己实现触摸事件,判断是哪个控件,计算 X , Y 坐标移动呢?非也,其实有简单的好办法。那就是:</p>    <p>使用 ViewDragHelper</p>    <p>ViewDragHelper 是一个非常棒的东西,好用,简单,不需要你去计算。2013年谷歌 I/O 大会上介绍了两个新的 layout: SlidingPaneLayout 和 DrawerLayout,现在这两个类被广泛的运用,其实研究他们的源码你会发现这两个类都运用了 ViewDragHelper 来处理拖动。ViewDragHelper 是 framework 中不为人知却非常有用的一个工具。</p>    <p>ViewDragHelper 解决了 Android 中手势处理过于复杂的问题,在 DrawerLayout 出现之前,侧滑菜单都是由第三方开源代码实现的,其中著名的当属 MenuDrawer ,MenuDrawer 重写 onTouchEvent 方法来实现侧滑效果,代码量很大,实现逻辑也需要很大的耐心才能看懂。如果每个开发人员都从这么原始的步奏开始做起,那对于安卓生态是相当不利的。所以说 ViewDragHelper 等的出现反映了安卓开发框架已经开始向成熟的方向迈进。</p>    <p>关于 ViewDragHelper 的具体用法,这里不过多赘述,想了解的,在网上一搜,有非常多的文章都在介绍它的基本使用方法。</p>    <h3>再次</h3>    <p>再次,我们该如何把拖动的视图的位置,保存住呢?又该如何在重新打开应用的时候按照我们自己组合和重新排列的布局显示呢?其实方法也一样很简单,那就是:</p>    <p>记住每个子控件拖拽后的位置,并保存,在 onLayout 方法中,读取记录的位置</p>    <p>在这里,我给每个视图和控件都增加了一个 tag ,在拖拽的时候根据 tag 知道拖拽的是哪个控件和视图,然后记录位置,写入 SharedPreferences 文件中,在 onLayout 方法中读取文件,根据记录的位置布局,这样,再次打开应用时,就会根据自己拖拽和组合的方式排列。</p>    <h3>最后</h3>    <p>最后,有一个问题就是,相对布局会根据自己初始的位置有覆盖层级的,先写的在下面,后写的控件在上面,拖拽的时候,怎么把下面的提到上面来呢?方法也很简单,那就是:</p>    <p>使用 child.bringToFront() 方法</p>    <p>bringToFront() 方法就是干这个事的,会把操作的视图,提到最上层来。</p>    <h2> </h2>    <p> </p>    <p>项目主页:<a href="http://www.open-open.com/lib/view/home/1494315149012">http://www.open-open.com/lib/view/home/1494315149012</a></p>    <p> </p>