首页 > 系统 > Android > 正文

Android ViewDragHelper实现京东、淘宝拖拽详情功能的实现

2019-10-22 18:12:39
字体:
来源:转载
供稿:网友

先上效果图,如果大家感觉不错,请参考实例代码,效果图如下所述:

Android,ViewDragHelper,拖拽

要实现这个效果有三种方式:

① 手势

② 动画
③ android/106181.html">ViewDragHelper

这里我使用的是ViewDragHelper类.

public class ViewDragLayout extends ViewGroup {  //垂直方向的滑动速度  private static final int VEL_THRESHOLD = 300;  //垂直方向的滑动距离  private static final int DISTANCE_THRESHOLD = 300;  //上面可见的View  private View mTopView;  //下面详情View  private View mBottomView;  //ViewDragHelper实例  private ViewDragHelper mViewDragHelper;  private GestureDetectorCompat mGestureDetectorCompat;  private int mFirstHeight;  public ViewDragLayout(Context context) {    super(context);    init();  }  public ViewDragLayout(Context context, AttributeSet attrs) {    super(context, attrs);    init();  }  public ViewDragLayout(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init();  }  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)  public ViewDragLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {    super(context, attrs, defStyleAttr, defStyleRes);    init();  }  private void init() {    mViewDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());    mGestureDetectorCompat = new GestureDetectorCompat(getContext(), new YScrollDetector());  }  @Override  protected void onFinishInflate() {    super.onFinishInflate();    mTopView = getChildAt(0);    mBottomView = getChildAt(1);   }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    if (mTopView.getTop() == 0) {      mTopView.layout(l, 0, r, b-t );      mBottomView.layout(l, 0, r, b-t );      mFirstHeight = mTopView.getMeasuredHeight();      mBottomView.offsetTopAndBottom(mFirstHeight);    }else{         mTopView.layout(l, mTopView.getTop(), r, mTopView.getBottom());      mBottomView.layout(l, mBottomView.getTop(), r, mBottomView.getBottom());    }  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    measureChildren(widthMeasureSpec,heightMeasureSpec);    int maxWidth = MeasureSpec.getSize(widthMeasureSpec);    int maxHeight = MeasureSpec.getSize(heightMeasureSpec);    setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0),        resolveSizeAndState(maxHeight, heightMeasureSpec, 0));  }  private class DragHelperCallback extends ViewDragHelper.Callback {    @Override    public boolean tryCaptureView(View child, int pointerId) {      return true;    }    /**     * @param child     * @param top     * @param dy     * @return     */    @Override    public int clampViewPositionVertical(View child, int top, int dy) {      int finalTop=top;      if (child == mTopView) {        if (top > 0) {          finalTop=0;        }      }else if(child==mBottomView){               if(top<0){          finalTop=0;        }      }      return finalTop;    }    @Override    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {      if (changedView == mTopView) {        mBottomView.offsetTopAndBottom(dy);      }else if (changedView==mBottomView){        mTopView.offsetTopAndBottom(dy);      }      ViewCompat.postInvalidateOnAnimation(ViewDragLayout.this);    }    /**     *     * @param releasedChild     * @param xvel 水平方向的速度(向右为正)     * @param yvel 竖直方向的速度(向下为正)     */    @Override    public void onViewReleased(View releasedChild, float xvel, float yvel) {      animTopOrBottom(releasedChild, yvel);    }  }  //动画实现滚动  private void animTopOrBottom(View releasedChild, float yvel) {    int finalTop=0;    if (releasedChild == mTopView) {      if (yvel < -VEL_THRESHOLD || (releasedChild.getTop() < -DISTANCE_THRESHOLD)) {        finalTop=-mFirstHeight;      }    } else if (releasedChild == mBottomView) {      if (yvel > VEL_THRESHOLD || (releasedChild.getTop() > DISTANCE_THRESHOLD)) {        finalTop=mFirstHeight;      }    }    if (mViewDragHelper.smoothSlideViewTo(releasedChild, 0, finalTop)) {      ViewCompat.postInvalidateOnAnimation(this);    }  }  @Override  public void computeScroll() {    if (mViewDragHelper.continueSettling(true)) {      ViewCompat.postInvalidateOnAnimation(this);    }  }  //是否拦截手势操作  @Override  public boolean onInterceptTouchEvent(MotionEvent ev) {    if (mTopView.getTop() < 0 && mTopView.getBottom() > 0) {      return false;    }    boolean isCanTouch = mGestureDetectorCompat.onTouchEvent(ev);    boolean shouldIntercept = mViewDragHelper.shouldInterceptTouchEvent(ev);    if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {      mViewDragHelper.processTouchEvent(ev);    }    return isCanTouch&&shouldIntercept;  }  //将touch事件交给ViewDragHelper处理  @Override  public boolean onTouchEvent(MotionEvent event) {     mViewDragHelper.processTouchEvent(event);    return true;  }  //垂直方向上才滚动  private class YScrollDetector extends GestureDetector.SimpleOnGestureListener {    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {      return Math.abs(distanceY) > Math.abs(distanceX);    }  }}

使用ViewDragLayout

<gesture.com.cn.widget.ViewDragLayout    android:id="@+id/view_drag_layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <FrameLayout      android:id="@+id/top_fragment_view"      android:layout_width="match_parent"      android:layout_height="match_parent"      />    <FrameLayout      android:id="@+id/bottom_fragment_view"      android:layout_width="match_parent"      android:layout_height="match_parent"/></gesture.com.cn.widget.ViewDragLayout>

bottom_fragment_view中使用了ScrollView,但是原生是不行的,所以这里我又将ScrollView重写了一下

这里主要是处理dispatchTouchEvent(MotionEvent ev)方法,判断将touch事件交给自己处理还是交给父View处理

public class CustomScrollView extends ScrollView {   //滚动临界值  private int mTouchSlop;  //获取初始X坐标  private float mRawX;  //获取初始Y坐标  private float mRawY;  //是否向上滑动  private boolean mCanScrollUp;  //是否向下滑动  private boolean mCanScrollDown;  public CustomScrollView(Context context) {    super(context);    init();  }  public CustomScrollView(Context context, @Nullable AttributeSet attrs) {    super(context, attrs);    init();  }  public CustomScrollView(Context context, @Nullable AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    init();  }  private void init() {    ViewConfiguration configuration = ViewConfiguration.get(getContext());    mTouchSlop = configuration.getScaledTouchSlop();  }  @Override  public boolean dispatchTouchEvent(MotionEvent ev) {    switch (ev.getActionMasked()) {      case MotionEvent.ACTION_DOWN:        mRawX = ev.getRawX();        mRawY = ev.getRawY();        mCanScrollUp = canScrollingUp();        mCanScrollDown = canScrollingDown();        //表示子View要自己消费这次事件,告诉父View不拦截这次的事件。        getParent().requestDisallowInterceptTouchEvent(true);        break;      case MotionEvent.ACTION_MOVE:        float xDis = Math.abs(mRawX - ev.getRawX());        float yDis = Math.abs(mRawY - ev.getRawY());        if (yDis > xDis && yDis > mTouchSlop) {          if (mRawY < ev.getRawY() && mCanScrollUp) {            //表示子View不消费这次事件,告诉父View拦截这次的事件。            getParent().requestDisallowInterceptTouchEvent(false);            return false;          }          if (mRawY > ev.getRawY() && mCanScrollDown) {            //表示子View不消费这次事件,告诉父View拦截这次的事件。            getParent().requestDisallowInterceptTouchEvent(false);            return false;          }        }        break;    }    return super.dispatchTouchEvent(ev);  }  /**   * 手指向下滑动(内容向上滑动)   * @return   */  private boolean canScrollingUp() {    if (ViewCompat.canScrollVertically(this, -1)) {      return false;    } else {      return true;    }  }  /**   * 手指向上滑动(内容向下滑动)   * @return   */  private boolean canScrollingDown() {    if (ViewCompat.canScrollVertically(this, 1)) {      return false;    } else {      return true;    }  }}

好了,具体拖拽代码就是这些了,界面我用的两个Fragment,相信大家也看出来了。里面大家换成自己的业务UI就可以了。

以上所述是小编给大家介绍的Android ViewDragHelper实现京东、淘宝拖拽详情功能的实现,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表