当前位置:网站首页>Recyclerview paging slide
Recyclerview paging slide
2022-07-05 11:57:00 【asahi_ xin】
frame
First step : preparation
api 'com.android.support:recyclerview-v7:26.1.0'
PagingScrollHelper
public class PagingScrollHelper {
private RecyclerView mRecyclerView = null;
private MyOnScrollListener mOnScrollListener = new MyOnScrollListener();
private MyOnFlingListener mOnFlingListener = new MyOnFlingListener();
private int offsetY = 0;
private int offsetX = 0;
private int startY = 0;
private int startX = 0;
enum ORIENTATION {
HORIZONTAL, VERTICAL, NULL
}
private ORIENTATION mOrientation = ORIENTATION.HORIZONTAL;
public void setUpRecycleView(RecyclerView recycleView) {
if (recycleView == null) {
throw new IllegalArgumentException("recycleView must be not null");
}
mRecyclerView = recycleView;
// Handle sliding
recycleView.setOnFlingListener(mOnFlingListener);
// Set scrolling monitor , Record the status of scrolling , And the total offset
recycleView.setOnScrollListener(mOnScrollListener);
// Record the position where the scroll starts
recycleView.setOnTouchListener(mOnTouchListener);
// Get the direction of scrolling
updateLayoutManger();
}
public void updateLayoutManger() {
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
if (layoutManager != null) {
if (layoutManager.canScrollVertically()) {
mOrientation = ORIENTATION.VERTICAL;
} else if (layoutManager.canScrollHorizontally()) {
mOrientation = ORIENTATION.HORIZONTAL;
} else {
mOrientation = ORIENTATION.NULL;
}
if (mAnimator != null) {
mAnimator.cancel();
}
startX = 0;
startY = 0;
offsetX = 0;
offsetY = 0;
}
}
/** * Get total pages */
public int getPageCount() {
if (mRecyclerView != null) {
if (mOrientation == ORIENTATION.NULL) {
return 0;
}
if (mOrientation == ORIENTATION.VERTICAL && mRecyclerView.computeVerticalScrollExtent() != 0) {
return mRecyclerView.computeVerticalScrollRange() / mRecyclerView.computeVerticalScrollExtent();
} else if (mRecyclerView.computeHorizontalScrollExtent() != 0) {
return mRecyclerView.computeHorizontalScrollRange() / mRecyclerView.computeHorizontalScrollExtent();
}
}
return 0;
}
private ValueAnimator mAnimator = null;
public void scrollToPosition(int position) {
if (mAnimator == null) {
mOnFlingListener.onFling(0, 0);
}
if (mAnimator != null) {
int startPoint = mOrientation == ORIENTATION.VERTICAL ? offsetY : offsetX, endPoint = 0;
if (mOrientation == ORIENTATION.VERTICAL) {
endPoint = mRecyclerView.getHeight() * position;
} else {
endPoint = mRecyclerView.getWidth() * position;
}
if (startPoint != endPoint) {
mAnimator.setIntValues(startPoint, endPoint);
mAnimator.start();
}
}
}
public class MyOnFlingListener extends RecyclerView.OnFlingListener {
@Override
public boolean onFling(int velocityX, int velocityY) {
if (mOrientation == ORIENTATION.NULL) {
return false;
}
// Get the page where scrolling is started index
int p = getStartPageIndex();
// The beginning and end of the scroll
int endPoint = 0;
int startPoint = 0;
// If it's vertical
if (mOrientation == ORIENTATION.VERTICAL) {
startPoint = offsetY;
if (velocityY < 0) {
p--;
} else if (velocityY > 0) {
p++;
}
// More different speeds to judge the direction of rolling
// Be careful , Here's a trick , When the speed is 0 Scroll the page that will start when , That is to realize page reset
endPoint = p * mRecyclerView.getHeight();
} else {
startPoint = offsetX;
if (velocityX < 0) {
p--;
} else if (velocityX > 0) {
p++;
}
endPoint = p * mRecyclerView.getWidth();
}
if (endPoint < 0) {
endPoint = 0;
}
// Use animation to handle scrolling
if (mAnimator == null) {
mAnimator = new 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;
// Through here RecyclerView Of scrollBy Method to realize scrolling .
mRecyclerView.scrollBy(0, dy);
} else {
int dx = nowPoint - offsetX;
mRecyclerView.scrollBy(dx, 0);
}
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Callback monitor
if (null != mOnPageChangeListener) {
mOnPageChangeListener.onPageChange(getPageIndex());
}
// Repair double click item bug
mRecyclerView.stopScroll();
startY = offsetY;
startX = offsetX;
}
});
} else {
mAnimator.cancel();
mAnimator.setIntValues(startPoint, endPoint);
}
mAnimator.start();
return true;
}
}
public class MyOnScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
//newState==0 Indicates that scrolling stops , At this point, you need to deal with rollback
if (newState == 0 && mOrientation != ORIENTATION.NULL) {
boolean move;
int vX = 0, vY = 0;
if (mOrientation == ORIENTATION.VERTICAL) {
int absY = Math.abs(offsetY - startY);
// If you slide more than half of the screen, you need to slide to the next page
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) {
// At the end of scrolling, record the offset of scrolling
offsetY += dy;
offsetX += dx;
}
}
private MyOnTouchListener mOnTouchListener = new MyOnTouchListener();
private boolean firstTouch = true;
public class MyOnTouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
// Record the coordinates when the finger is pressed
if (firstTouch) {
// for the first time touch May be ACTION_MOVE or ACTION_DOWN, So use this way to judge
firstTouch = false;
startY = offsetY;
startX = offsetX;
}
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
firstTouch = true;
}
return false;
}
}
private int getPageIndex() {
int p = 0;
if (mRecyclerView.getHeight() == 0 || mRecyclerView.getWidth() == 0) {
return p;
}
if (mOrientation == ORIENTATION.VERTICAL) {
p = offsetY / mRecyclerView.getHeight();
} else {
p = offsetX / mRecyclerView.getWidth();
}
return p;
}
private int getStartPageIndex() {
int p = 0;
if (mRecyclerView.getHeight() == 0 || mRecyclerView.getWidth() == 0) {
// Can't handle without width and height
return p;
}
if (mOrientation == ORIENTATION.VERTICAL) {
p = startY / mRecyclerView.getHeight();
} else {
p = startX / mRecyclerView.getWidth();
}
return p;
}
private onPageChangeListener mOnPageChangeListener;
public void setOnPageChangeListener(onPageChangeListener listener) {
mOnPageChangeListener = listener;
}
public interface onPageChangeListener {
void onPageChange(int index);
}
}
VerticalDecoration
public class VerticalDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
private static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
private static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public VerticalDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
private void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
Second parts : call
// Initialize the paging tool class
PagingScrollHelper pagingScrollHelper = new PagingScrollHelper();
mRecyclerView.setAdapter(mainAdapter);
pagingScrollHelper.setUpRecycleView(mRecyclerView);
mRecyclerView.setHorizontalScrollBarEnabled(true);
VerticalDecoration verticalDecoration = new VerticalDecoration(this, LinearLayoutManager.HORIZONTAL);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.addItemDecoration(verticalDecoration);
pagingScrollHelper.updateLayoutManger();
pagingScrollHelper.scrollToPosition(0);
边栏推荐
- Redirection of redis cluster
- [deploy pytoch project through onnx using tensorrt]
- Programmers are involved and maintain industry competitiveness
- Codeforces Round #804 (Div. 2)
- 程序员内卷和保持行业竞争力
- 15 methods in "understand series after reading" teach you to play with strings
- Open3d European clustering
- codeforces每日5题(均1700)-第五天
- 2022年国内云管平台厂商哪家好?为什么?
- 13.(地图数据篇)百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
猜你喜欢
Redirection of redis cluster
报错ModuleNotFoundError: No module named ‘cv2.aruco‘
Idea set the number of open file windows
无线WIFI学习型8路发射遥控模块
【pytorch 修改预训练模型:实测加载预训练模型与模型随机初始化差别不大】
yolov5目标检测神经网络——损失函数计算原理
Thoughts and suggestions on the construction of intelligent management and control system platform for safe production in petrochemical enterprises
Is it difficult to apply for a job after graduation? "Hundreds of days and tens of millions" online recruitment activities to solve your problems
Hiengine: comparable to the local cloud native memory database engine
[crawler] bugs encountered by wasm
随机推荐
The most comprehensive new database in the whole network, multidimensional table platform inventory note, flowus, airtable, seatable, Vig table Vika, flying Book Multidimensional table, heipayun, Zhix
Codeforces Round #804 (Div. 2)
简单解决redis cluster中从节点读取不了数据(error) MOVED
Riddle 1
Sentinel sentinel mechanism of master automatic election in redis master-slave
Solve the grpc connection problem. Dial succeeds with transientfailure
yolov5目標檢測神經網絡——損失函數計算原理
1个插件搞定网页中的广告
多表操作-子查询
pytorch-softmax回归
liunx禁ping 详解traceroute的不同用法
Open3D 网格(曲面)赋色
投资理财适合女生吗?女生可以买哪些理财产品?
[yolov5.yaml parsing]
View all processes of multiple machines
Prevent browser backward operation
[pytorch pre training model modification, addition and deletion of specific layers]
15 methods in "understand series after reading" teach you to play with strings
中非 钻石副石怎么镶嵌,才能既安全又好看?
[leetcode] wild card matching