代码如下:
public class DragLayout extends FrameLayout {
int touchSlop =0;
private ViewDragHelper mViewDragHelper;
private View mChildView;
private float minHeightToMove = 0.5f;
public DragLayout(@NonNull Context context) {
this(context, null);
}
public DragLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DragLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
//获取最小滑动距离 没用到
touchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();
mViewDragHelper = ViewDragHelper.create(this, dragCallback);
}
private int newHeight=0;
private ViewDragHelper.Callback dragCallback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return true;
}
//水平滑动
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
// Log.e("left:", left + "");
// Log.e("dx:", dx + "");
return super.clampViewPositionHorizontal(child, left, dx);
}
//竖直滑动
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
Log.e("top:", top + "");
Log.e("dy:", dy+ "");
//Math.min(0,top) 因为我想实现的是向上滑动,防止滑动到最大距离
//top为正数的时候回有向下操作回晃动
//Math.min(Math.min(0,top),mChildView.getHeight()) 这个是我想要向上滑动
//最外层的abs取移动的距离
newHeight=Math.abs(Math.min(Math.min(0,top),mChildView.getHeight()));
return -newHeight;
}
//结束拖动
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
float realHeight=mChildView.getHeight();
//滑动的距离/真实的高度 > 我设定的比例
if ((newHeight/realHeight)>minHeightToMove){
//回弹到最上方
mViewDragHelper.settleCapturedViewAt(0,-(int)realHeight);
}else {
//回到起始点
mViewDragHelper.settleCapturedViewAt(0,0);
}
//需要刷新布局否则不会自动回弹
invalidate();
}
};
@Override
public boolean onInterceptHoverEvent(MotionEvent event) {
//拦截事件
return mViewDragHelper.shouldInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//消费事件
mViewDragHelper.processTouchEvent(event);
return true;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() > 0) {
mChildView = getChildAt(0);
}
}
//滑动停止后的惯性操作
@Override
public void computeScroll() {
super.computeScroll();
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
xml代码:
<com.fqb.myapplication.DragLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:paddingTop="20dp" android:paddingBottom="20dp" android:background="@color/colorAccent" android:layout_width="match_parent" android:layout_height="200dp"> <TextView android:text="测试" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> </com.fqb.myapplication.DragLayout>