Dragger模块

134 篇文章 0 订阅
87 篇文章 1 订阅
Dragger模块


Dragger模块是项目的一个base模块,用于实现对所挂接View的drag<Touch>位移.
这个模块设计的理念很好,体现了V<View> 和 C<TouchController> 完全独立分离的思想,
随便一个View,被Dragger挂接上即可在parent内跟随Touch移动.
其实本质上就是之前Tab模块中封装的TouchController,只不过这里直接将其独立出去,将
要drag的View也作为TouchController的一个参数<挂接View>.


<1>Dragger既然是脱胎与内部类TouchController, 那么基本原理也是一致的, 接管了所挂接View的TouchEvent,
根据Action的Down/Move/Up来做不同操作和状态设计,不同的是,出于简化需求的目的,Dragger没有使用进阶的
GestureDetector 来检测Scroll/fling/SingleTap这些复合操作,而是直接处理Down/Move/Up这些源生动作.


<2>Dragger内会维护一个指向挂接View的引用,以及相应的setter.


<3>Dragger里全部用PonitF来存储 View的action_down的,RawX/Y, view原点相对parent的X/Y,以及Parent的size.
这个是细枝末节,怎么存都无所谓. 就算使用int保存都没关系,不要求十分精准.


<4>这种方式得以实现的原因是,一旦某次Touch事务<从down到up的一系列TouchEvent>被某个View明确接管,那么就算本次Touch
事务的Move/Up移出了View的Touch范围,依然是由View来接管<MotionEvent的相对坐标也会保持正确>, 不存在移出收到Action_cancel的情况,
这样,只要down在了View内就可以抓住这一轮TouchEvent直到up.


<5>被挂接的View类也需要做相应的适配, 可以内部构造一个Dragger<不过这样就失去了挂接的灵活性>,
重要的一点是, 需要在dispatchTouchEvent这一步优先将TouchEvent交给dragger来处理,处理不了<false>的情况下才采用默认的dispatchTouchEvent
<返回false代表回吐本次Touch事务,不再接受本次事务的后继TouchEvent>.
onInterceptTouchEvent和onTouchEvent应该也都可以.


<6>Dragger相当于一个View TouchEvent的拦截器,对每种Action做出响应, 没有被拦截的TouchEvent会继续原来的流程,而被拦截的则就此中断旅程.
(1)Action_Down: 这一步记录下down点的RawX/Y, 以及此时View的原点的相对X/Y. 获取View的parent的size. 然后放行此TouchEvent,
                 这一步只是做个登记,不一定真的会用到,如果中间没来Action_Move,直接来了个Action_Up,那么就没有用.
(2)Action_Move:  有Move,代表着开始drag了<down的时候会有一个flag来表示已经down了,会检测这个down flag作为条件>,
                 除了确保先down以外, 还做了一个第一次Move时Move量的检测<为了确保第一次Move的时候移动的不是太远>,
                 检测方法很多啦,这里是以down的RawX/Y为中心做了一个边长为X的Rect来看Move的MotionEvent的RawX/Y是不是被contain了,
                 <一个简单得到以X/Y为中心,边长为L的Rect的方法:
new 一个空Rect,即(0,0,0,0),然后inset(-L,-L),外扩L,然后offset到(X,Y)即可,不用自己再计算了>
                 以上通过以后, 就根据累计Move量<因为一切是以down时View的相对X/Y为基准的>
计算出View相对parent的新的原点X/Y,layout之即实现位移效果.
                 累计Move量很好求,本次Move的MotionEvent的RawX/Y - down点的RawX/Y即可,再与down时View的相对X/Y相加即可,
                 为了确保不超出parent,还要做一个clamp来限定新的相对X/Y值; 最后layout(X,Y,X+width, Y+height)
<触发invalidate,不会触发measure/layout>。
(3)Action_UP: 记录Up时View的原点相对X/Y,在后面parent layout时会用来恢复挂接View的位置,然后放行.  


<7>dragger还有一个功能,在orentation变化的时候<或者其他导致parent layout的情况>,
会按照原来View在parent的位置将被挂接的View以合适的位置出现在旋转过的屏幕上,不然会有
旋转完以后,被挂接View不在可视范围内<超出了parent的可视范围>的问题, 或者是http://blog.csdn.net/fyfcauc/article/details/44199487
分析的,parent layout之后将View打回这种Layout方式默认的原位.
为了实现对parent的监视,dragger还implememts了ViewTreeObserver.OnGlobalLayoutListener<ViewTreeObserver还是挺有讲头的,不过项目用的不多>,
这个Listener可以在View被layout的时候触发<Notifies registered listeners that a global layout happened.>,ViewTreeObserver只能从View取得,不能new.
在上面Listener的回调中利用这次parent的W/H和之前保存的parent的W/H做比率<要考虑之前没有的情况>,一系列运算之后得到新位置,layout之,
然后更新View的相对X/Y和parent的新size.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
介绍:用ViewDragHelper实现的activity切换动画。运行效果:使用说明: 你可以将这个库当成view来用:将DraggerView添加到root layout,并且在里面加入两个layout。<com.github.library.DraggerView     android:layout_width="match_parent"     android:layout_height="match_parent"     dragger_layout:drag_view_id="@ id/drag_view"     dragger_layout:shadow_view_id="@ id/shadow_view"     dragger_layout:drag_position="top">       <FrameLayout           android:id="@ id/shadow_view"           android:layout_width="match_parent"           android:layout_height="match_parent"           android:background="@color/transparent"           android:visibility="invisible"/>         <LinearLayout           android:id="@ id/drag_view"           android:layout_width="match_parent"           android:layout_height="match_parent"/>   </com.github.library.DraggerView>style文件中这样设置<style name="YourTheme" parent="Theme.AppCompat.Light.DarkActionBar">     <item name="android:windowIsTranslucent">true</item>       <item name="android:windowBackground">@android:color/transparent</item>       <item name="android:windowNoTitle">true</item>       <item name="windowActionBar">false</item>       <item name="android:windowAnimationStyle">@null</item> </style>manifest中<activity     android:name="com.github.dragger.BaseActivity"     android:theme="@style/YourTheme"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值