Android 사용자 정의 레이아웃 세로 뷰 퍼 구현

Android 사용자 정의 레이아웃 세로 뷰 퍼 구현
효과 그림:

이 사용자 정의 컨트롤 에 대한 지식:
ViewGroup 의 onMeasure 와 onLayout 의 쓰기 사용자 정의
신축성 스크롤 스크롤 스크롤 러 사용법
속도 궤적 추적 기 Velocity Tracker 의 용법
미끄럼 사건 충돌 을 어떻게 처리 합 니까?
dispatchTouchEvent:(외부 차단)스크롤 레이아웃 의 부모 레이아웃 을 알려 줍 니 다.터치 이 벤트 를 언제 차단 해 야 하 는 지,터치 이 벤트 를 언제 차단 하지 말 아야 하 는 지 알려 줍 니 다.
onInterceptTouchEvent:(내부 차단)ScrollLayout 는 내부 자 View 의 터치 이 벤트 를 언제 차단 해 야 하 는 지,내부 자 View 의 터치 이 벤트 를 언제 차단 하지 말 아야 하 는 지 알려 줍 니 다.
터치 슬라이딩 처리 방법:
  • 먼저 포석 을 실현 하고 손가락 의 미끄럼 에 따라 scrollBy
  • 를 미끄러진다.
  • 경계 조건 처리(이번 처리 경 계 는 저속 미끄럼 상황 에서 만 적용)
  • 빠 른 미끄럼 Velocity Tracker 라면 경계 문 제 를 다시 고려 해 야 합 니 다(위 에서 고려 한 경계 문 제 는 빠 른 미끄럼 상황 에 적용 되 지 않 습 니 다)
  • 저속 미끄럼 이 라면 손가락 이 미 끄 러 지 는 방향 과 레이아웃 이 미 끄 러 지 는 거리 에 따라 판단 하여 페이지 가 그 페이지 로 미 끄 러 지 는 것 을 확인 해 야 합 니 다.여 기 는 탄성 미끄럼 Scroller
  • 를 사 용 했 습 니 다.
  • 어 려 운 점 이 생 겼 습 니 다.알고리즘,
  • 
    //              ,
    //             
    if (Math.abs(velocityY) > criticalVelocityY) {//         ,           
    //    、     ,               ,          (        ,         ,         ) 
    if (shouZhiXiangXiaHuaDong) { 
    if (currentPage > 1) {//★★★★★★★★    ,       ,     ,  ★(currentPage-2) 
    mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY()); 
    currentPage--; 
    } 
    } else { 
    if (currentPage < childCount) {//★★★★★★★    ,        ,     ,  ★currentPage 
    mScroller.startScroll(0, getScrollY(), 0, childHeight * currentPage - getScrollY()); 
    currentPage++; 
    } 
    } 
    Log.e("eee", currentPage + "");
    
    총결산
    알고리즘 을 쓰 려 고 할 때 급 하 게 한꺼번에 쓰 려 고 하지 마 세 요.그러면 맹목적 인 것 에 빠 집 니 다.한 걸음 한 걸음 코드 를 실현 하고 마지막 에 규칙 을 찾 도록 지도 해 야 합 니 다.요약,통 항 공식 과 유사 한 방법 입 니 다.
    코드 는 다음 과 같 습 니 다.(주석 이 완전 합 니 다)
    
    package beautlful.time.com.beautlfultime.view;
    
    import android.content.Context;
    import android.support.v4.view.ViewConfigurationCompat;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.VelocityTracker;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.view.ViewGroup;
    import android.widget.Scroller;
    
    /**
     *   :    viewgroup          match_parent   ,             
     *   :    viewgroup,    padding   ,      ScrollerLayout     padding,            ,
     *     padding  ,    ScrollerLayout           (     ),        padding 
     *     viewgroup        ,         ,   :
     * Android Scroller    ,  Scroller        
     * http://blog.csdn.net/guolin_blog/article/details/48719871
     */
    public class VerticalViewPager extends ViewGroup {
      int currentPage = 1;
    
      /**
       *        
       */
      private VelocityTracker mVelocityTracker;
    
      /**
       *              
       */
      private final int mMaxVelocity;
    
      /**
       *       id,          ,     
       */
      private int mPointerId;
    
      /**
       *           
       */
      private float velocityY;
    
      /**
       *             ,      ,          ,             
       */
      private int criticalVelocityY = 2500;
    
      /**
       *            
       */
      private Scroller mScroller;
    
      /**
       *              
       */
      private int mTouchSlop;
    
      /**
       *           
       */
      private float mYDown;
    
      /**
       *            
       */
      private float mYMove;
    
      /**
       *     ACTION_MOVE        
       */
      private float mYLastMove;
    
      /**
       *           
       */
      private int topBorder;
    
      /**
       *           
       */
      private int bottomBorder;
    
    
      /**
       *       (            ,  match_parent)
       */
      private int childHeight;
    
    
      /**
       *          
       */
      private boolean shouZhiXiangXiaHuaDong;
      private int childCount;
    
    
      public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        //    ,  Scroller   
        mScroller = new Scroller(context);
        ViewConfiguration configuration = ViewConfiguration.get(context);
        //   TouchSlop 
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
        //             
        mMaxVelocity = ViewConfiguration.get(context).getMaximumFlingVelocity();
      }
    
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
          View childView = getChildAt(i);
          //  ScrollerLayout            
          measureChild(childView, widthMeasureSpec, heightMeasureSpec);
        }
      }
    
      @Override
      protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
          /**
           *                  
           */
          int preChildViewTotalHeight = 0;
          for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            //  ScrollerLayout                  
            if (i == 0) {
              childView.layout(
                  0,
                  0,
                  childView.getMeasuredWidth(),
                  childView.getMeasuredHeight());
    
            } else {
              childView.layout(
                  0,
                  preChildViewTotalHeight,
                  childView.getMeasuredWidth(),
                  preChildViewTotalHeight + childView.getMeasuredHeight());
            }
            preChildViewTotalHeight += childView.getMeasuredHeight();
    
          }
          //         
          topBorder = getChildAt(0).getTop();
          bottomBorder = getChildAt(getChildCount() - 1).getBottom();
    
          childHeight = getChildAt(0).getMeasuredHeight();
    
    
        }
      }
    
    
      private int downX;
      private int downY;
    
      //       ScrollLayout    ,           ,            
      public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
          case MotionEvent.ACTION_DOWN:
            //   ScrollerLayout             
            getParent().requestDisallowInterceptTouchEvent(true);
            downX = (int) ev.getX();
            downY = (int) ev.getY();
            break;
          case MotionEvent.ACTION_MOVE:
            int moveX = (int) ev.getX();
            int moveY = (int) ev.getY();
    
            //     ViewPager      ,ViewPager     ,            
            if (Math.abs(moveY - downY) < Math.abs(moveX - downX)) {
              getParent().requestDisallowInterceptTouchEvent(false);
            } else {
              //     ViewPager        ,ScrollerLayout        
              getParent().requestDisallowInterceptTouchEvent(true);
            }
    
            break;
    
          case MotionEvent.ACTION_CANCEL:
    
    
            break;
          case MotionEvent.ACTION_UP:
    
    
            break;
        }
        return super.dispatchTouchEvent(ev);
      }
    
    
      //   ScrollLayout              View     ,           View     
      @Override
      public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
          case MotionEvent.ACTION_DOWN:
            //▲▲▲1.       id,          ,     
            mPointerId = ev.getPointerId(0);
            mYDown = ev.getRawY();
            mYLastMove = mYDown;
            break;
          case MotionEvent.ACTION_MOVE:
            mYMove = ev.getRawY();
            float diff = Math.abs(mYMove - mYDown);
            mYLastMove = mYMove;
            //         TouchSlop  ,        ,        
            if (diff > mTouchSlop) {
              return true;
            }
            break;
        }
        return super.onInterceptTouchEvent(ev);
      }
    
    
      @Override
      public boolean onTouchEvent(MotionEvent event) {
        //▲▲▲2. VelocityTracker  MotionEvent
        acquireVelocityTracker(event);
        switch (event.getAction()) {
          case MotionEvent.ACTION_MOVE:
    
            //▲▲▲3.      
            mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
            velocityY = mVelocityTracker.getYVelocity(mPointerId);
    
            mYMove = event.getRawY();
            int scrolledY = (int) (mYLastMove - mYMove);//       ,         ,       
    
    
            if (getScrollY() + scrolledY < topBorder) {//          ,         (   、    ,           )
              scrollTo(0, topBorder);
              return true;//★★★★★★★★★★★★★★★★    true  false       ,          。
            } else if (getScrollY() + getHeight() + scrolledY > bottomBorder) {//         ,          
              scrollTo(0, bottomBorder - getHeight());
              return true;//★★★★★★★★★★★★★★★★★    true  false       ,          。
            }
    
            scrollBy(0, scrolledY);//  move ,      
            if (mYDown <= mYMove) {//★★★        ,      ,  mYDown,   mYLastMove
              shouZhiXiangXiaHuaDong = true;//      
            } else {
              shouZhiXiangXiaHuaDong = false;//      
            }
            mYLastMove = mYMove;
            break;
          case MotionEvent.ACTION_UP:
    //        4.▲▲▲  VelocityTracker
            releaseVelocityTracker();
    
            //    ,      ,                              ,      invalidate();
            if (Math.abs(velocityY) > criticalVelocityY) {//         ,          
    //             、     ,               ,          (        ,         ,         )
              if (shouZhiXiangXiaHuaDong) {
                if (currentPage > 1) {//★★★★★★★★    ,       ,     ,  ★(currentPage-2)
                  mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
                  currentPage--;
                }
              } else {
                if (currentPage < childCount) {//★★★★★★★    ,        ,     ,  ★currentPage
                  mScroller.startScroll(0, getScrollY(), 0, childHeight * currentPage - getScrollY());
                  currentPage++;
                }
              }
              Log.e("eee", currentPage + "");
            } else {//           ,     ,            
    
    //          、     ,                    ,(            ,          ,        )
              if ((getScrollY() >= childHeight * (currentPage - 1) + childHeight / 2 && !shouZhiXiangXiaHuaDong)) {
    //                   ,             
                mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage) - getScrollY());
                currentPage++;
    
              } else if ((getScrollY() < childHeight * (currentPage - 1) + childHeight / 2 && !shouZhiXiangXiaHuaDong)) {
    //                   ,              
                mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 1) - getScrollY());
    
              } else if
                  ((getScrollY() <= childHeight * (currentPage - 2) + childHeight / 2
                      && shouZhiXiangXiaHuaDong)) {
    //                    ,             
                mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
                currentPage--;
              } else if
                  ((getScrollY() > childHeight * (currentPage - 2) + childHeight / 2
                      && shouZhiXiangXiaHuaDong)) {
    //                    ,              
                mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 1) - getScrollY());
              }
    
     
    
     
    
    
              /* if ((getScrollY() >= childHeight && !shouZhiXiangXiaHuaDong)//      ,              ,viewgroup      
                  || ((getScrollY() >= (totalChildHeight - firstChildHeight - lastChildHeight) && shouZhiXiangXiaHuaDong))) {//      ,                  ,viewgroup      
    //                     (          ,           )       ,   viewgroup     Viewgroup    ,
    //                      600,           getScrollX,
    //            ,           600-getScrollX(),          
                mScroller.startScroll(0,getScrollY(), 0, (totalChildHeight - firstChildHeight) - getScrollY());
              } else if ((getScrollY() <= (totalChildHeight - firstChildHeight - lastChildHeight) && shouZhiXiangXiaHuaDong)//      ,                ,viewgroup      
                  || (getScrollY() <= childHeight && !shouZhiXiangXiaHuaDong)) {//      ,                ,viewgroup      
    
    //                     ,   viewgroup     Viewgroup    ,
    //                   ,     viewgroup     0,           getScrollX,
    //            ,           0-getScrollX(),          
                mScroller.startScroll(0,getScrollY(), 0, 0 - getScrollY());
              }*/
            }
    //            invalidate()  
            invalidate();
            break;
    
          case MotionEvent.ACTION_CANCEL:
    //       5.▲▲▲  VelocityTracker
            releaseVelocityTracker();
    
            break;
        }
        return super.onTouchEvent(event);
      }
    
    
      @Override
      public void computeScroll() {
        //    ,  computeScroll()  ,              
        if (mScroller.computeScrollOffset()) {
          scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
          invalidate();
        }
      }
    
      /**
       * @param event  VelocityTracker  MotionEvent
       * @see VelocityTracker#obtain()
       * @see VelocityTracker#addMovement(MotionEvent)
       */
      private void acquireVelocityTracker(final MotionEvent event) {
        if (null == mVelocityTracker) {
          mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
      }
    
      /**
       *   VelocityTracker
       *
       * @see VelocityTracker#clear()
       * @see VelocityTracker#recycle()
       */
      private void releaseVelocityTracker() {
        if (null != mVelocityTracker) {
          mVelocityTracker.clear();
          mVelocityTracker.recycle();
          mVelocityTracker = null;
        }
      }
    
    
       /*  getScrollX()    viewgroup  View scrollTo(int x, int y)  scrollBy(int x, int y)   X    
    //            ,         ,    viewgroup       ,   
    //                            
            Log.e("qqq","getX():"+event.getX());
    //                            
            Log.e("qqq","getRawX():"+event.getRawX());*/
    }
    
    
    레이아웃 파일
    
     <beautlful.time.com.beautlfultime.view.VerticalViewPager
          android:id="@+id/verticalViewPager"
          android:layout_width="match_parent"
          android:layout_height="150dp">
          <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
          android:background="@android:color/holo_orange_dark"
            android:text="        " />
    
          <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorAccent"
            android:text="  " />
    
          <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimary"
            android:text="  " />
          <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorAccent"
            android:text="  " />
    
     
    
        </beautlful.time.com.beautlfultime.view.VerticalViewPager>
    
    
    
     읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기