Android View DragHelper 는 경 동,타 오 바 오 드래그 상세 기능 의 실현 을 실현 합 니 다.

먼저 효과 도 를 올 리 고 여러분 이 괜찮다 면 실례 코드 를 참고 하 십시오.효과 도 는 다음 과 같 습 니 다.

이 효 과 를 실현 하려 면 세 가지 방식 이 있다.
① 제스처
② 애니메이션
③ 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 로 바 꾸 면 됩 니 다.
위 에서 말 한 것 은 편집장 님 께 서 소개 해 주신 안 드 로 이 드 뷰 드 래 곤 헬 퍼 가 경 동,타 오 바 오 드래그 상세 기능 의 실현 을 실현 하 는 것 입 니 다.여러분 께 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 저 에 게 메 시 지 를 남 겨 주세요.편집장 님 께 서 신속하게 답 해 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기