效果视频 上连接
直接上代码
本文主要是根据ViewDragHelper 工具类 提供的效果
public class MDragLayout extends RelativeLayout { private ViewDragHelper mViewDragHelper ; private View mDragView ; public MDragLayout(@NonNull Context context) { this(context,null); } public MDragLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public MDragLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mViewDragHelper = ViewDragHelper.create(this,mCall); } private boolean isOpen = false ; private float mDownY ; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(isOpen){ return true ; // 只要是 底部的布局显示 就把事件拦截 让他能收起来 } switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: mDownY = ev.getY(); mViewDragHelper.processTouchEvent(ev); break; case MotionEvent.ACTION_MOVE: if(ev.getY()>mDownY && mDragView.canScrollVertically(1)){ return true ; } break; } return super.onInterceptTouchEvent(ev); } @Override protected void onFinishInflate() { super.onFinishInflate(); if(getChildCount()>2){ throw new RuntimeException("最多添加兩個view"); } mDragView = getChildAt(1) ; // 獲取到上面的 view } private int belowViewHeight ; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); belowViewHeight = getChildAt(0).getMeasuredHeight() ; } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } ViewDragHelper.Callback mCall = new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(@NonNull View child, int pointerId) { return mDragView ==child; // 只拖动上面 } @Override public int clampViewPositionVertical(@NonNull View child, int top, int dy) { if(top<0){ top=0; } if(top>belowViewHeight){ top =belowViewHeight ; } return top; } /** * 左右拖動子view */ // @Override // public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) { // return left; // } @Override public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) { if(mDragView.getTop()>belowViewHeight/2){ mViewDragHelper.settleCapturedViewAt(0,belowViewHeight); isOpen = true; }else { mViewDragHelper.settleCapturedViewAt(0,0); isOpen = false ; } invalidate(); } }; /** * 响应滚动 */ @Override public void computeScroll() { if(mViewDragHelper.continueSettling(true)){ invalidate(); } } } j简单布局文件 参考
<com.example.customviewapp.view.MDragLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:background="#628929" android:layout_width="match_parent" android:layout_height="300dp" /> <androidx.recyclerview.widget.RecyclerView android:background="#989993" android:layout_width="match_parent" android:id="@+id/review" android:layout_height="match_parent" /> </com.example.customviewapp.view.MDragLayout>