仿豌豆荚ViewPager下拉

系统 1444 0

在豌豆荚的应用详情页中有个ViewPager布局,该布局头部添加了一个可上下收展的view用于显示应用资料。实现思路基本上就是利用ViewDragHelper进行拖动来控制头部的view的布局。当TopView可见时,手势事件被拖动层截获控制上下拖动达到TopView的折叠和展开效果。当TopView不可见时,手势事件交由ViewPager进行控制达到ListView正常滚动,并在ListView的onScroll滚动监听中判断ListView是否触顶。如果触顶则下拉拖动ViewPager显示TopView.

项目已经上传到Github的 DragTopLayout .
先看下效果图:

实现过程


1.继承一个FrameLayout,在FrameLayout中控制子View拖动。FrameLayout初始化中实例化一个ViewDragHelper对象。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">ViewDragHelper.create(<span class="hljs-keyword" style="outline:none!important; font-weight:bold">this</span>, <span class="hljs-number" style="color:#0880;outline:none!important;">1.0</span>f, callback);</code>
      

2.参数中callback即为拖动过程中所有的事件回调,实现一个ViewDragHelper.Callback()。
Callback中的所用到得方法如下:

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)"><span class="hljs-comment" style="color:#888888;outline:none!important;">// 判断child是否是拖动的目标</span>
tryCaptureView(View child, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> pointerId)
<span class="hljs-comment" style="color:#888888;outline:none!important;">// 拖动位置的处理,可以处理拖动过程中的最高位置或者最低位置</span>
clampViewPositionVertical(View child, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> top, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dy)
<span class="hljs-comment" style="color:#888888;outline:none!important;">// 拖动后view位置的改变</span>
onViewPositionChanged(View view, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> left, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> top, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dx, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dy)
<span class="hljs-comment" style="color:#888888;outline:none!important;">// 拖动手势释放后的处理</span>
onViewReleased(View releasedChild, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">float</span> xvel, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">float</span> yvel)
<span class="hljs-comment" style="color:#888888;outline:none!important;">// 拖动状态的改变</span>
onViewDragStateChanged(<span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> state)</code>
      

3.覆盖onInterceptTouchEvent和onTouchEvent方法,将事件拦截处理。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">boolean</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">onInterceptTouchEvent</span>(MotionEvent ev) {
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">return</span> shouldIntercept && dragHelper.shouldInterceptTouchEvent(ev);
    }

    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">boolean</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">onTouchEvent</span>(MotionEvent event) {
        dragHelper.processTouchEvent(event);
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">return</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">true</span>;
    }</code>
      

4.覆盖computeScroll方法,用以实现拖动后的滚动效果

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">void</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">computeScroll</span>() {
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">if</span> (dragHelper.continueSettling(<span class="hljs-keyword" style="outline:none!important; font-weight:bold">true</span>)) {
            ViewCompat.postInvalidateOnAnimation(<span class="hljs-keyword" style="outline:none!important; font-weight:bold">this</span>);
        }
    }</code>
      

5.简单地拖动差不多实现了,下面就需要在Callback中进行拖动事件的自定义逻辑处理了。
先利用tryCaptureView判断当前touch的view是否是目标拖动view,返回true则拖动处理,false不处理。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)"><span class="hljs-keyword" style="outline:none!important; font-weight:bold">return</span> child == dragContentView;</code>
      

在clampViewPositionVertical方法中处理拖动的最高高度不超过上边界。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">clampViewPositionVertical</span>(View child, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> top, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dy) {
            <span class="hljs-keyword" style="outline:none!important; font-weight:bold">return</span> Math.min(topViewHeight, Math.max(top, getPaddingTop()));
    }</code>
      

在onViewPositionChanged方法中控制拖动后新位置的处理。因为拖动过程中还需对TopView进行相应地处理,所以在方法内记录拖动的top位置,并在onLayout回调方法中处理最新位置的现实。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">void</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">onViewPositionChanged</span>(View changedView, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> left, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> top, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dx, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> dy) {
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">super</span>.onViewPositionChanged(changedView, left, top, dx, dy);
        contentTop = top;
        requestLayout();
    }</code>
      

当释放手势后判断手势方向利用settleCapturedViewAt方法进行处理最终滚动位置。其中yvel参数>0代表快速往下滑动,否则为快速往上滑动。

        <code class="language-java hljs " style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(0,0,0); display:block; outline:none!important; background-color:rgb(240,240,240)">    <span class="hljs-annotation" style="color:#888888;outline:none!important;">@Override</span>
    <span class="hljs-keyword" style="outline:none!important; font-weight:bold">public</span> <span class="hljs-keyword" style="outline:none!important; font-weight:bold">void</span> <span class="hljs-title" style="color:#8800;outline:none!important; font-weight:bold">onViewReleased</span>(View releasedChild, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">float</span> xvel, <span class="hljs-keyword" style="outline:none!important; font-weight:bold">float</span> yvel) {
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">super</span>.onViewReleased(releasedChild, xvel, yvel);
        <span class="hljs-comment" style="color:#888888;outline:none!important;">// yvel > 0 Fling down || yvel < 0 Fling up</span>
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">int</span> top;
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">if</span> (yvel > <span class="hljs-number" style="color:#0880;outline:none!important;">0</span> || contentTop > topViewHeight) {
            top = topViewHeight + getPaddingTop();
        } <span class="hljs-keyword" style="outline:none!important; font-weight:bold">else</span> {
            top = getPaddingTop();
        }
        <span class="hljs-keyword" style="outline:none!important; font-weight:bold">if</span> (wizard.enableSliding) {
            dragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
        }
        postInvalidate();
    }</code>
      

这样就处理好了拖动的所有事件了。具体代码可参考Github上的项目。


文章转载页http://blog.csdn.net/chenupt/article/details/43228671#comments

仿豌豆荚ViewPager下拉


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论