QQ 사 이 드 슬라이딩 효과 모방 ViewDragHelper

9558 단어 android
전재 출처 를 밝 혀 주 십시오:http://blog.csdn.net/wei_chong_chong/article/details/50807353
Google 은 support 라 이브 러 리 에서 DrawerLayout 와 SlidingPaneLayout 두 개의 레이아웃 을 제공 하여 사 이 드 바 가 미 끄 러 지 는 효 과 를 개발 합 니 다.
이 두 레이아웃 뒤에 강력 한 기능 을 가 진 View DragHelper 류 가 있 습 니 다. View DragHelper 를 통 해 다양한 미끄럼, 드래그 수 요 를 실현 할 수 있 고 각종 미끄럼 문 제 를 해결 하 는 궁 극적인 묘수 입 니 다.
(실현 원리: 슬라이딩 메뉴 의 프레임 워 크 라 고 하 는데 사실은 우리 가 레이아웃 을 사용자 정의 한 것 이다. 이 사용자 정의 레이아웃 에서 슬라이딩 메뉴 의 기능 을 잘 실현 한 다음 에 Activity 의 레이아웃 파일 에 사용자 정의 레이아웃 을 도입 하면 이 Activity 는 슬라이딩 메뉴 의 기능 을 가진다.)
다음은 QQ 사 이 드 슬라이더 를 모방 하 는 효 과 를 가 져 옵 니 다.
1. ViewDragHelper 초기 화 (나중에 구조 방법 에서 이 초기 화 방법 을 사용 하면 초기 화 작업 을 할 수 있 습 니 다. 주의: 모든 구조 방법 을 호출 해 야 합 니 다) ViewGroup 은 보통 ViewGroup 의 내부 에 정의 되 고 정적 공장 방법 을 통 해 코드 를 초기 화 합 니 다.
private void initView() {
		mViewDragHelper = ViewDragHelper.create(this, callback);
	}

첫 번 째 인 자 는 감청 할 View 입 니 다. 보통 View Group, 즉 parentView 가 필요 합 니 다.두 번 째 매개 변 수 는 Callback 리 셋 입 니 다. 이 리 셋 은 바로 이 View DragHelper 의 논리 적 핵심 입 니 다. 아래 에 놓 고 설명 하 겠 습 니 다.
2. 차단 이벤트
차단 이벤트 방법 을 다시 쓰 고 이 벤트 를 View DragHelper 에 전달 하여 처리 합 니 다. 코드 는 다음 과 같 습 니 다.
@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return mViewDragHelper.shouldInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//        ViewDragHelper,       
		mViewDragHelper.processTouchEvent(event);
		return true;
	}
이 점 의 지식 은 안 드 로 이 드 이벤트 메커니즘 부분 에 속 하 므 로 나중에 보충 할 것 이다.
3. compute Scroll () 처리
(View DragHelper 내부 도 Scroller 를 통 해 부 드 럽 게 이동 합 니 다) 아래 템 플 릿 코드 를 사용 할 수 있 습 니 다.
@Override
	public void computeScroll() {
		if (mViewDragHelper.continueSettling(true)) {
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

4. 콜백 처리
private ViewDragHelper.Callback callback =
			new ViewDragHelper.Callback() {

		//           
		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			//       child mMainView     
			return mMainView == child;
		}

미끄럼 방법 (수평, 수직) 이 두 가지 있 습 니 다. 미끄럼 효 과 를 실현 하려 면 이 두 가지 방법 을 다시 써 야 합 니 다.
기본 반환 값 은 0 이 고 미 끄 러 지지 않 기 때문에 우 리 는 수평 으로 미 끄 러 지기 만 하면 되 기 때문에 수직 으로 미 끄 러 지 는 방법 으로 그 를 0 으로 되 돌려 줍 니 다. (다시 쓰 지 않 아 도 되 고 기본 값 은 0 이 잖 아 요)
//       
		@Override
		public int clampViewPositionVertical(View child, int top, int dy) {
			return 0;
		}

		//       
		@Override
		public int clampViewPositionHorizontal(View child, int left, int dx) {
			return left;
		}
clampView Position Vertical (View child, int top, int dy) 의 매개 변수 top 은 수직 방향 에서 child 가 이동 하 는 거 리 를 나타 내 고 dy 는 이전의 증 가 량 을 비교 하 는 것 을 나타 낸다.동 리 수직 방법 매개 변 수 는 의미 가 유사 하 다.일반적으로 top 과 left 만 되 돌려 주면 되 지만 padding 등 속성 을 더욱 정확하게 계산 해 야 할 때 left 를 처리 하고 적당 한 크기 의 값 을 되 돌려 야 합 니 다.
위의 이 세 가지 방법 을 다시 쓰 면 가장 기본 적 인 미끄럼 효 과 를 실현 할 수 있 습 니 다. 코드 는 다음 과 같 습 니 다.
<pre name="code" class="java">private ViewDragHelper.Callback callback =
			new ViewDragHelper.Callback() {

		//           
		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			//       child mMainView     
			return mMainView == child;
		}

		
		//       
		@Override
		public int clampViewPositionVertical(View child, int top, int dy) {
			return 0;
		}

		//       
		@Override
		public int clampViewPositionHorizontal(View child, int left, int dx) {
			return left;
		}

};
 
  
 

重写onViewReleased(),通过重写这个方法,可以非常简单地实现当手指离开屏幕后实现的操作,当然这个方法内部是通过Scroller类实现的部分代码如下

//        
		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			super.onViewReleased(releasedChild, xvel, yvel);
			//              
			if (mMainView.getLeft() < 500) {
				//    
				//   Scroller startScroll  
				mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
				ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
			} else {
				//    
				mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
				ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
			}
		}
	};

MainView 이동 후 왼쪽 거리 가 500 픽 셀 이하 일 때 smoothSlidViewTo () 방법 으로 MainView 를 초기 상태 로 복원 합 니 다. 즉,
좌 표 는 (0, 0) 점 이 고 왼쪽 여백 이 500 보다 크 면 MainView 를 (300, 0) 좌표 로 이동 합 니 다. 즉, MenuView 를 표시 합 니 다.
마지막 으로 하위 뷰 를 각각 MenuView 와 MainView 로 정의 하고 getChildAt (0) 에서 가 져 온 레이아웃 을 왼쪽 레이아웃 으로 하고 getChildAt (1) 에서 가 져 온 레이아웃 을 오른쪽 레이아웃 으로 사용 합 니 다.그리고 onSizeChanged () 방법 에서 View 폭 얻 기;
@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		mMenuView = getChildAt(0);
		mMainView = getChildAt(1);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mWidth = mMenuView.getMeasuredWidth();
	}

실현 과정 은 다음 과 같다.
먼저 DragView Group 클래스 계승 FrameLayout 를 쓰 겠 습 니 다.
public class DragViewGroup extends FrameLayout {

	private ViewDragHelper mViewDragHelper;
	private View mMenuView, mMainView;
	private int mWidth;

	public DragViewGroup(Context context) {
		super(context);
		initView();
	}

	public DragViewGroup(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();
	}

	public DragViewGroup(Context context,
			AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initView();
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		mMenuView = getChildAt(0);
		mMainView = getChildAt(1);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mWidth = mMenuView.getMeasuredWidth();
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return mViewDragHelper.shouldInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//        ViewDragHelper,       
		mViewDragHelper.processTouchEvent(event);
		return true;
	}

	private void initView() {
		mViewDragHelper = ViewDragHelper.create(this, callback);
	}

	private ViewDragHelper.Callback callback =
			new ViewDragHelper.Callback() {

		//           
		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			//       child mMainView     
			return mMainView == child;
		}

		//    View   
		@Override
		public void onViewCaptured(View capturedChild,
				int activePointerId) {
			super.onViewCaptured(capturedChild, activePointerId);
		}

		//        ,  idle,dragging
		@Override
		public void onViewDragStateChanged(int state) {
			super.onViewDragStateChanged(state);
		}

		//           ,        scale 
		@Override
		public void onViewPositionChanged(View changedView,
				int left, int top, int dx, int dy) {
			super.onViewPositionChanged(changedView, left, top, dx, dy);
		}

		//       
		@Override
		public int clampViewPositionVertical(View child, int top, int dy) {
			return 0;
		}

		//       
		@Override
		public int clampViewPositionHorizontal(View child, int left, int dx) {
			return left;
		}

		//        
		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			super.onViewReleased(releasedChild, xvel, yvel);
			//              
			if (mMainView.getLeft() < 500) {
				//    
				//   Scroller startScroll  
				mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
				ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
			} else {
				//    
				mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
				ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
			}
		}
	};

	@Override
	public void computeScroll() {
		if (mViewDragHelper.continueSettling(true)) {
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}
}

그리고 레이아웃 파일 에서 직접 인용 하면 됩 니 다. 사용 방법 은 사용자 정의 컨트롤 과 유사 합 니 다.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.qqviewdraghelper.MainActivity" >

    <com.example.qqviewdraghelper.DragViewGroup
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_blue_light" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Menu" />
        </FrameLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_orange_dark" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Main" />
        </FrameLayout>
    </com.example.qqviewdraghelper.DragViewGroup>

</RelativeLayout>

좋은 웹페이지 즐겨찾기