项目已经上传到Github的DragTopLayout.
先看下效果图:
实现过程
1.继承一个FrameLayout,在FrameLayout中控制子View拖动。FrameLayout初始化中实例化一个ViewDragHelper对象。
ViewDragHelper.create(this, 1.0f, callback);
2.参数中callback即为拖动过程中所有的事件回调,实现一个ViewDragHelper.Callback()。
Callback中的所用到得方法如下:
1
2
3
4
5
6
7
8
9
10
|
// 判断child是否是拖动的目标
tryCaptureView(View child,
int
pointerId)
// 拖动位置的处理,可以处理拖动过程中的最高位置或者最低位置
clampViewPositionVertical(View child,
int
top,
int
dy)
// 拖动后view位置的改变
onViewPositionChanged(View view,
int
left,
int
top,
int
dx,
int
dy)
// 拖动手势释放后的处理
onViewReleased(View releasedChild,
float
xvel,
float
yvel)
// 拖动状态的改变
onViewDragStateChanged(
int
state)
|
3.覆盖onInterceptTouchEvent和onTouchEvent方法,将事件拦截处理。
1
2
3
4
5
6
7
8
9
10
|
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
return
shouldIntercept && dragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
dragHelper.processTouchEvent(event);
return
true
;
}
|
4.覆盖computeScroll方法,用以实现拖动后的滚动效果
1
2
3
4
5
6
|
@Override
public
void
computeScroll() {
if
(dragHelper.continueSettling(
true
)) {
ViewCompat.postInvalidateOnAnimation(
this
);
}
}
|
5.简单地拖动差不多实现了,下面就需要在Callback中进行拖动事件的自定义逻辑处理了。
先利用tryCaptureView判断当前touch的view是否是目标拖动view,返回true则拖动处理,false不处理。
return child == dragContentView;
在clampViewPositionVertical方法中处理拖动的最高高度不超过上边界。
1
2
3
4
|
@Override
public
int
clampViewPositionVertical(View child,
int
top,
int
dy) {
return
Math.min(topViewHeight, Math.max(top, getPaddingTop()));
}
|
在onViewPositionChanged方法中控制拖动后新位置的处理。因为拖动过程中还需对TopView进行相应地处理,所以在方法内记录拖动的top位置,并在onLayout回调方法中处理最新位置的现实。
1
2
3
4
5
6
|
@Override
public
void
onViewPositionChanged(View changedView,
int
left,
int
top,
int
dx,
int
dy) {
super
.onViewPositionChanged(changedView, left, top, dx, dy);
contentTop = top;
requestLayout();
}
|
当释放手势后判断手势方向利用settleCapturedViewAt方法进行处理最终滚动位置。其中yvel参数>0代表快速往下滑动,否则为快速往上滑动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Override
public
void
onViewReleased(View releasedChild,
float
xvel,
float
yvel) {
super
.onViewReleased(releasedChild, xvel, yvel);
// yvel > 0 Fling down || yvel < 0 Fling up
int
top;
if
(yvel >
0
|| contentTop > topViewHeight) {
top = topViewHeight + getPaddingTop();
}
else
{
top = getPaddingTop();
}
if
(wizard.enableSliding) {
dragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
}
postInvalidate();
}
|
这样就处理好了拖动的所有事件了。具体代码可参考Github上的项目。
https://github.com/chenupt/DragTopLayout