Android 에서 RecyclerView 가 페이지 를 나 누 어 스크롤 하 는 방법 에 대한 상세 한 설명
12367 단어 androidrecyclerview페 이 징 스크롤
최근 회사 프로젝트 가 하나의 수 요 를 실현 하려 면 다음 과 같은 기능 을 만족 시 켜 야 한다.
1)list 목록 을 표시 합 니 다.item 수량 이 고정 되 지 않 습 니 다.
2)페이지 넘 기기 기능 을 실현 하여 한 번 에 한 페이지 씩 넘 기기.
3)한 페이지 로 넘 기 는 기능 을 실현 한다.
다음은 RecyclerView 를 통 해 이 수 요 를 실현 하 는 과정(효과 도 는 다음 과 같다)을 소개 한다.
기능 실현
2.1 OnTouchListener 는 현재 미 끄 러 지기 시작 한 위 치 를 기록 합 니 다.
페이지 를 넘 기 려 면 먼저 우 리 는 앞으로 넘 기 는 지 뒤로 넘 기 는 지 확인 해 야 합 니 다.여 기 는 기록 을 통 해 페이지 를 넘 기기 전의 현재 위치 와 미 끄 러 진 후의 위 치 를 비교 해 보면 알 수 있 습 니 다.아래 는 손가락 터치 로 누 를 때 미 끄 러 지 는 위 치 를 현재 미 끄 러 지 는 위치 로 선택 하 십시오.
//
private int offsetY = 0;
private int offsetX = 0;
//
private int startY = 0;
private int startX = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
//
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//
startY = offsetY;
startX = offsetX;
}
return false;
}
}
자,우리 가 미끄럼 방향 을 확정 하면 다음 에 고려 해 야 할 것 은 어떻게 미끄럼 을 실현 하 는 것 입 니까?2.2 scrollto(int x,int y)와 scrollBy(int x,int y)가 미 끄 러 짐
미끄럼 우리 가 가장 쉽게 생각 할 수 있 는 방법 은
scrollTo(int x, int y)
과scrollBy(int x, int y)
두 가지 방법 이다.scrollTo(int x, int y)
은 현재 View 의 내용 을 특정한 위치 로 미 끄 러 뜨리 는 것 이다.scrollBy(int x, int y)
현재 View 내용 을 현재 위치 에 비해 일정한 거 리 를 미 끄 러 뜨리 는 것 이다.사실은scrollBy(int x, int y)
내 부 는scrollTo(int x, int y)
방법 으로 이 루어 진 것 이다.그러나 소스 코드 를 간단하게 보 니 RecyclerView 는 이 방법 을 지원 하지 않 는 다.
@Override
public void scrollTo(int x, int y) {
Log.w(TAG, "RecyclerView does not support scrolling to an absolute position. "
+ "Use scrollToPosition instead");
}
그래서 여기 서 우 리 는scrollTo(int x, int y)
를 사용 하여 미끄럼 을 실현 하 는 것 을 선택한다.2.3 OnFling Listener 와 OnScroll Listener 가 미끄럼 시 기 를 호출 합 니 다.
위 에서 우 리 는
scrollBy(int x, int y)
을 사용 하여 미끄럼 을 실현 하기 로 결정 했다.그러면 지금 우 리 는scrollBy(int x, int y)
이 방법의 호출 시 기 를 확정 해 야 한다.우 리 는 우리 가 RecyclerView 를 미 끄 러 질 때 보통 두 가지 상황 으로 나 뉜 다 는 것 을 알 고 있다.하 나 는 손가락 이 화면 위 에서 천천히 미 끄 러 지 는 것(Scroll)이 고 다른 하 나 는 빠 른 속도 로 미 끄 러 지 는 것(onFling)이다.한 번 의 조 사 를 통 해RecyclerView 에 이 두 가지 상태의 감청 이 있 는 것 을 발 견 했 습 니 다.그러면 이 두 가지 상태의 방법 정 의 를 살 펴 보 겠 습 니 다.먼저 보 겠 습 니 다scrollBy(int x, int y)
.참고:RecyclerView 의 OnFlingListener 를 사 용 했 기 때문에 RecycleView 버 전 은 recyclerview-v7:25.0.0 이상 이 어야 합 니 다.
/**
* This class defines the behavior of fling if the developer wishes to handle it.
* <p>
* Subclasses of {@link OnFlingListener} can be used to implement custom fling behavior.
*
* @see #setOnFlingListener(OnFlingListener)
*/
public static abstract class OnFlingListener {
/**
* Override this to handle a fling given the velocities in both x and y directions.
* Note that this method will only be called if the associated {@link LayoutManager}
* supports scrolling and the fling is not handled by nested scrolls first.
*
* @param velocityX the fling velocity on the X axis
* @param velocityY the fling velocity on the Y axis
*
* @return true if the fling washandled, false otherwise.
*/
public abstract boolean onFling(int velocityX, int velocityY);
}
방법 에 대한 설명 도 잘 쓰 여 있 습 니 다.이 방법 이 호출 되 고 트 루 로 돌아 갈 때 시스템 은 미끄럼 을 처리 하지 않 고 미끄럼 을 우리 자신 에 게 맡 깁 니 다.그래서 우 리 는 이 방법 을 감청 할 수 있 습 니 다.우리 가 빠 른 미끄럼 을 실행 할 때 이 방법 에서 미 끄 러 질 거 리 를 계산 하고 실행onFling(int velocityX, int velocityY)
을 통 해 미끄럼 을 실현 한 다음 에 true 로 돌아 가 미끄럼 을 우리 가 처리 하고 시스템 처리 가 필요 없다 는 것 을 표시 합 니 다.처리 코드 는 다음 과 같 습 니 다:
//
private int offsetY = 0;
private int offsetX = 0;
//
private int startY = 0;
private int startX = 0;
// view
private int lastItemPosition = -1;
// view
private int firstItemPosition = -2;
// itemView
private int totalNum;
@Override
public boolean onFling(int velocityX, int velocityY) {
if (mOrientation == ORIENTATION.NULL) {
return false;
}
// index
int page = getStartPageIndex();
//
int endPoint = 0;
int startPoint = 0;
//
if (mOrientation == ORIENTATION.VERTICAL) {
// , scrollBy
startPoint = offsetY;
if (velocityY < 0) {
page--;
} else if (velocityY > 0) {
page++;
} else if (pageNum != -1) {
if (lastItemPosition + 1 == totalNum) {
mRecyclerView.scrollToPosition(0);
}
page = pageNum - 1;
}
//
// mRecyclerView
endPoint = page * mRecyclerView.getHeight();
} else {
startPoint = offsetX;
if (velocityX < 0) {
page--;
} else if (velocityX > 0) {
page++;
} else if (pageNum != -1) {
if (lastItemPosition + 1 == totalNum) {
mRecyclerView.scrollToPosition(0);
}
page = pageNum - 1;
}
endPoint = page * mRecyclerView.getWidth();
}
//
if (mAnimator == null) {
mAnimator = ValueAnimator.ofInt(startPoint, endPoint);
mAnimator.setDuration(300);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int nowPoint = (int) animation.getAnimatedValue();
if (mOrientation == ORIENTATION.VERTICAL) {
int dy = nowPoint - offsetY;
if (dy == 0) return;
// RecyclerView scrollBy 。
mRecyclerView.scrollBy(0, dy);
} else {
int dx = nowPoint - offsetX;
mRecyclerView.scrollBy(dx, 0);
}
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
//
@Override
public void onAnimationEnd(Animator animation) {
//
if (null != mOnPageChangeListener) {
mOnPageChangeListener.onPageChange(getPageIndex());
}
// ,
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
// layoutManager LinearLayoutManager
// LinearLayoutManager view
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;
// view
lastItemPosition = linearManager.findLastVisibleItemPosition();
// view
firstItemPosition = linearManager.findFirstVisibleItemPosition();
}
totalNum = mRecyclerView.getAdapter().getItemCount();
if (totalNum == lastItemPosition + 1) {
updateLayoutManger();
}
if (firstItemPosition == 0) {
updateLayoutManger();
}
}
});
} else {
mAnimator.cancel();
mAnimator.setIntValues(startPoint, endPoint);
}
mAnimator.start();
return true;
}
}
OnScrollListener 스크롤 감청 방법 다시 보기:
public abstract static class OnScrollListener {
/**
* Callback method to be invoked when RecyclerView's scroll state changes.
*
* @param recyclerView The RecyclerView whose scroll state has changed.
* @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE},
* {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}.
*/
public void onScrollStateChanged(RecyclerView recyclerView, int newState){}
/**
* Callback method to be invoked when the RecyclerView has been scrolled. This will be
* called after the scroll has completed.
* <p>
* This callback will also be called if visible item range changes after a layout
* calculation. In that case, dx and dy will be 0.
*
* @param recyclerView The RecyclerView which scrolled.
* @param dx The amount of horizontal scroll.
* @param dy The amount of vertical scroll.
*/
public void onScrolled(RecyclerView recyclerView, int dx, int dy){}
}
이 감청 류 는 주로 두 가지 방법 이 있 는데 하 나 는scrollBy(int x, int y)
스크롤 상태 에 변화 호출 이 발생 하고onScrollStateChanged(RecyclerView recyclerView, int newState)
스크롤 과 스크롤 이 발생 하여 호출 이 완료 되 는 것 이다.이 두 개의 감청 이 있 습 니 다.우리 가 천천히 미 끄 러 지면onScrolled(RecyclerView recyclerView, int dx, int dy) RecyclerView
에서 감청 미끄럼 이 끝나 고 일정한 거 리 를 초과 하여 페이지 를 넘 길 수 있 습 니 다.onScrollStateChanged(RecyclerView recyclerView, int newState)
방법 을 통 해 현재 의 미끄럼 거 리 를 기록 할 수 있 습 니 다.처리 방법 은 다음 과 같다.
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
//
if (newState == RecyclerView.SCROLL_STATE_IDLE && mOrientation != ORIENTATION.NULL) {
boolean move;
int vX = 0, vY = 0;
if (mOrientation == ORIENTATION.VERTICAL) {
int absY = Math.abs(offsetY - startY);
//
move = absY > recyclerView.getHeight() / 2;
vY = 0;
if (move) {
vY = offsetY - startY < 0 ? -1000 : 1000;
}
} else {
int absX = Math.abs(offsetX - startX);
move = absX > recyclerView.getWidth() / 2;
if (move) {
vX = offsetX - startX < 0 ? -1000 : 1000;
}
}
//
mOnFlingListener.onFling(vX, vY);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
//
//
offsetY += dy;
offsetX += dx;
}
}
여기까지 우리 가 미끄럼 을 실현 하 는 방법 과 시 기 는 기본적으로 해결 되 었 다.나머지 는 미끄럼 위치 계산 과 미끄럼 효과 실현 이다.미끄럼 위치 계산 은 한 번 에 한 페이지 씩 미 끄 러 지 는 것 이다.이것 은 할 말 이 없 기 때문에 간단하게 말 해서 탄성 미끄럼 효 과 를 실현 한다.2.4 ValueAnimator 신축성 슬라이딩 효과 구현
우 리 는 만약 에 우리 가 직접
onScrolled(RecyclerView recyclerView, int dx, int dy)
이라는 방법 으로 미 끄 러 지 는 것 을 알 고 있다.그러면 천천히 미 끄 러 지 는 효과 가 없고 약간 어리둥절 해 보인다.그래서 여기 서 우 리 는 ValueAnimator 라 는 종 류 를 통 해 천천히 미 끄 러 지 는 효 과 를 실현 한다.이것 은 매우 간단 하 다.코드 를 직접 붙인다.
if (mAnimator == null) {
mAnimator = ValueAnimator.ofInt(startPoint, endPoint);
mAnimator.setDuration(300);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int nowPoint = (int) animation.getAnimatedValue();
if (mOrientation == ORIENTATION.VERTICAL) {
int dy = nowPoint - offsetY;
if (dy == 0) return;
// RecyclerView scrollBy 。
mRecyclerView.scrollBy(0, dy);
} else {
int dx = nowPoint - offsetX;
mRecyclerView.scrollBy(dx, 0);
}
}
});
2.5 어느 페이지 로 넘 기기여기 서 한 페이지 로 넘 기 는 실현 은 위의 기초 가 있 으 면 잘 이 루어 진다.바로 우리 가 이미 실현 한
scrollBy(int x, int y)
방법 을 직접 호출 한 다음 에 페이지 수 를 전달 하여 계산 하면 된다.
public void setPageNum(int page) {
this.pageNum = page;
mOnFlingListener.onFling(0, 0);
}
여기까지 앞에서 말 한 기능 은 이미 모두 실현 되 었 다.구체 적 인 코드 세부 사항 은 다음 을 보십시오.
github 주소:pagerecyclerview
로 컬 다운로드:여 기 를 클릭 하 세 요.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 안 드 로 이 드 개발 자 들 에 게 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.