QQ 사 이 드 슬라이딩 효과 모방 ViewDragHelper
9558 단어 android
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>
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.