在这里做了一个折叠列表的效果,先看下效果图
Gif_20180418_214031.gif
在这个效果这里我用的是ViewDragHelper来做的。先写一个类继承自FramLayout。在这个类的构造函数里创建出ViewDragHelper。
viewDragHelper = ViewDragHelper.create(this, mViewDragHelperCallBack);
在这里ViewDragHelper不能new出来,要去调用它的create方法,是因为它的构造函数私有化了。在它的两个参数里一个是当前的类也就是布局本身,类外一个要传入一个CallBack。在这个CallBack里面有可以让内部子view可以移动的方法。
private ViewDragHelper.Callback mViewDragHelperCallBack = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
//表示能能让前面的那个view滑动
return mListView == child;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
//控制前面的view滑动的范围
if (top<=0){
top=0;
}
if (top>= measuredHeight){
top = measuredHeight;
}
return top;
}
//在手指松开的时候,选择打开还是关闭
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (releasedChild == mListView){
if (mListView.getTop()>measuredHeight/2){
// 滚动到菜单的高度(打开)
viewDragHelper.settleCapturedViewAt(0,measuredHeight);
mMenuIsOpen = true;
}else {
mMenuIsOpen = false;
viewDragHelper.settleCapturedViewAt(0,0);
}
invalidate();
}
}
};
在这里我们用到了它的三个方法,第一个是表示滑动的是那个view,第二个是表示让view垂直滑动,第三个方法表示的事在滑动完之后可以让view停在那里的方法。当定义好这个自定义view之后,我们去写我们的布局
<?xml version="1.0" encoding="utf-8"?>
<com.example.myday14.MyVerticalListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mvLv"
tools:context="com.example.myday14.MainActivity">
<TextView
android:id="@+id/tv_change"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="后面" />
<com.example.myday14.MyListView
android:id="@+id/m_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#999999"
android:gravity="center"
/>
</com.example.myday14.MyVerticalListView>
写完之后我们在我们的代码里面给listview设置数据之后,就可以看到效果了。但是这个时候滑动还是有问题的,当我们滑动到后面这个view的高度时,向上滑动listview我们会发现listview不能回到开始的位置了,那是因为在向上滑动的时候,listview的滑动事件将,我们的自定义view的事件给拦截了,所以我们在我们的自定义view的onInterceptTouchEvent里面要处理这个事件,当我们抬起手指的时候,发现我们的菜单也就是后面的view全部显示出来的时候,我们要拦截listview的事件,而去相应父view也就是我们定义的view的事件
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//拿到按下时的y位置
mOldY = event.getY();
viewDragHelper.processTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
mMoveY = event.getY();
if ((mMoveY-mOldY)>0 && !canChildScrollUp()){
return true;
}
// 菜单打开要拦截
if (mMenuIsOpen) {
return true;
}
break;
}
return super.onInterceptHoverEvent(event);
}
我们定义了一个mMenuIsOpen来表示菜单是否打开,打开的时候我们就去返回true。
代码放到Github了
https://github.com/chenzhikaizg/MyListView
网友评论