android SlidingUpPanel (一)

本文探讨了Android第三方库SlidingUpPanel的实现原理,重点解析了ViewDragHelper在拖动处理中的作用,以及如何创建实例并实现回调接口。SlidingUpPanelLayout作为 ViewGroup 的扩展,通过添加两个子View并重写测量和布局方法,利用ViewDragHelper实现在屏幕底部向上滑动的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       最近做的项目里用到一个开源的第三方库SlidingUpPanel,其作用是将一个视图从底部往上拖拽到另一个视图之上,代码在github上可以下载到https://github.com/umano/AndroidSlidingUpPanel,其效果如下图所示:



具体的用法在github上也有,在此就不另做赘述,本文主要讨论其具体是如何实现的。下载源文件可以看到里面只有两个文件SlidingUpPanelLayout.java和 ViewDragHelper.java。

   一、ViewDragHelper.java

  首先来说说ViewDragHelper.java,可能有些看官已经对其有所了解,那么请忽略,本文讲的不好的地方也可以帮忙指出,一定虚心接受。

   在2013年谷歌i/o大会上介绍了两个新的layout: SlidingPaneLayout和DrawerLayout,研究过其源码的应该知道这两个类都使用了ViewDragHelper.java处理拖动SlidingPaneLayout与本文所讲的SlidingUpPanelLayout.java很像(有没有~~~),甚至其内部处理拖动的方式也都采用ViewDragHelper.java处理。

   ViewDragHelper.java在support v4中,官方的介绍如下:

ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup.

   用于自定义ViewGroup的一个工具类,为用户在父ViewGroup中拖动并且重新定位视图,提供了很多有用的操作以及状态跟踪方法。要获取到ViewDragHelper.java类的实例,可以调用该类的create()方法,该方法有两个,一个是两个参数的,一个是三个参数的。三个参数分别为:forParent第一个是指定监听的父视图;第二个参数sensitivity表示灵敏度,值越大代表越灵敏,通常为1.0 ;第三个参数是个回调接口cb,是ViewDragHelper与ViewGroup之间通信的桥梁,也是使用ViewDragHepler的关键。

   create方法调用ViewDragHelper的私有构造方法实例化该类,构造方法中进行成员变量的赋值等操作,其中有个mScroller(是不是看着眼熟,没错,ViewDragHelper的拖动其实是通过Scroller滚动类实现的,如果对Scroller不熟的看官可以找找这方面的资料)。

   上面讲到使用ViewDragHelper关键是回调接口Callback,实际上ViewDragHelper并不直接作用于要被拖动的View,而是使其控制的视图容器中的子View可以被拖动,如果要指定某个子view的行为,需要在Callback中实现:

   public static abstract class Callback {

        public void onViewDragStateChanged(int state) {}   //拖动状态改变时触发该方法

        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {} //视图位置改变触发该方法

        public void onViewCaptured(View capturedChild, int activePointerId) {}  //当子视图被捕获进行拖动时触发该方法

        public void onViewReleased(View releasedChild, float xvel, float yvel) {} // 当子视图失去被捕获时触发该方法

        public void onEdgeTouched(int edgeFlags, int pointerId) {}

        public boolean onEdgeLock(int edgeFlags) {

            return false;

        }

        public void onEdgeDragStarted(int edgeFlags, int pointerId) {}

        public int getOrderedChildIndex(int index) {

            return index;

        }

        public int getViewHorizontalDragRange(View child) {

            return 0;

        }

        public int getViewVerticalDragRange(View child) {

            return 0;

        }

        public abstract boolean tryCaptureView(View child, int pointerId);

        public int clampViewPositionHorizontal(View child, int left, int dx) {

            return 0;

        }

        public int clampViewPositionVertical(View child, int top, int dy) {

            return 0;

        }

    }

上面列出了Callback中定义的所有方法,tryCaptureView方法用于指定视图容器中的哪个view可以进行拖动;clampViewPositionHorizontal和clampViewPositionVertical两个方法用于具体实现拖动,是必须实现的;其他的方法根据需要进行实现。

    另外使用ViewDragHelper处理拖动,必须将拖动事件传递给ViewDragHelper,ViewDragHelper中定义了shouldInterceptTouchEvent和processTouchEvent方法对事件进行处理。

       ViewDragHelper就介绍到这里,讲的不好,逻辑性也不强,下面总结下使用ViewDragHelper的关键点:

       1、通过create方法获取到ViewDragHelper实例;

       2、根据需要实现Callback相关方法;

       3、将事件传递给ViewDragHelper(一般是在onInterceptTouchEvent和onTouchEvent中调用ViewDragHelper的shouldInterceptTouchEvent和processTouchEvent方法);

       还有其他诸如计算可以拖动的范围、完成拖动后的惯性操作这里就不做介绍了,感兴趣的可以研究下。

      二、SlidingUpPanelLayout

    终于进入到本文的主题了SlidingUpPanelLayout,其基本原理如下:

    1、继续于ViewGroup,并且在ViewGroup中添加两个子view,一个定义为mMainView,另一个定义为mSlideableView;

    2、重写ViewGroup的onMeasure、onLayout方法将两个子view在界面进行布局显示;

    3、通过ViewDragHelper实现将mSlideableView从底部往上拖动,并覆盖mMainView。

    

 (待续~~)

    


AndroidSlidingUpPanel个上拉面板, 就是向上滑动的时候往上飞出个显示面板控件, 该库效果在 Google Music, Google Maps and Rdio等 App 中用到。 效果图: 用法:使用com.sothree.slidinguppanel.SlidingUpPanelLayout作为您的活动布局的根元素。 布局必须设置为顶部或底部。请确保它有两个元素。 第个元素是你的主要布局。第二个元素是你的向上滑动面板布局。 主要布局应当具有的宽度和高度设置为match_parent。 滑动的布局的宽度应设置为match_parent;高度应设置为match_parent,WRAP_CONTENT或最大desireable高度。 如果您想定义高度屏幕为percetange,可将其设置为match_parent,滑动视图定义为layout_weight属性。  默认情况下,整个面板将作为拖动区域和将截获的点击和拖动事件。可以通过使用setDragView方法或umanoDragView属性限制牵引区到特定的图。 想了解更多信息,请参考示例代码:<com.sothree.slidinguppanel.SlidingUpPanelLayout     xmlns:sothree="http://schemas.android.com/apk/res-auto"     android:id="@ id/sliding_layout"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:gravity="bottom"     sothree:umanoPanelHeight="68dp"     sothree:umanoShadowHeight="4dp">     <TextView         android:layout_width="match_parent"         android:layout_height="match_parent"         android:gravity="center"         android:text="Main Content"         android:textSize="16sp" />     <TextView         android:layout_width="match_parent"         android:layout_height="match_parent"         android:gravity="center|top"         android:text="The Awesome Sliding Up Panel"         android:textSize="16sp" /> </com.sothree.slidinguppanel.SlidingUpPanelLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值