public class GalleryRecyclerView extends RecyclerView implements View.OnTouchListener, MyGalleryItemDecoration.OnItemSizeMeasuredListener {
private static final String TAG = "MainActivity_TAG";
public static final int LINEAR_SNAP_HELPER = 0;
public static final int PAGER_SNAP_HELPER = 1;
/**
* 滑动速度
*/
private int mFlingSpeed = 1000;
private int mInitPos = -1;
private AnimManager mAnimManager;
private MyScrollManager mScrollManager;
private MyGalleryItemDecoration mDecoration;
public MyGalleryItemDecoration getDecoration() {
return mDecoration;
}
public AnimManager getAnimManager() {
return mAnimManager;
}
public GalleryRecyclerView(Context context) {
this(context, null);
}
public GalleryRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public GalleryRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.GalleryRecyclerView);
int helper = ta.getInteger(R.styleable.GalleryRecyclerView_helper, LINEAR_SNAP_HELPER);
ta.recycle();
DLog.d(TAG, "GalleryRecyclerView constructor");
mAnimManager = new AnimManager();
attachDecoration();
attachToRecyclerHelper(helper);
//设置触碰监听
setOnTouchListener(this);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
}
private void attachDecoration() {
DLog.d(TAG, "GalleryRecyclerView attachDecoration");
mDecoration = new MyGalleryItemDecoration();
mDecoration.setOnItemSizeMeasuredListener(this);
addItemDecoration(mDecoration);
}
@Override
public boolean fling(int velocityX, int velocityY) {
velocityX = balanceVelocity(velocityX);
velocityY = balanceVelocity(velocityY);
return super.fling(velocityX, velocityY);
}
/**
* 返回滑动速度值
*
* @param velocity int
* @return int
*/
private int balanceVelocity(int velocity) {
if (velocity > 0) {
return Math.min(velocity, mFlingSpeed);
} else {
return Math.max(velocity, -mFlingSpeed);
}
}
/**
* 连接RecyclerHelper
*
* @param helper int
*/
private void attachToRecyclerHelper(int helper) {
DLog.d(TAG, "GalleryRecyclerView attachToRecyclerHelper");
mScrollManager = new MyScrollManager(this);
mScrollManager.initScrollListener();
mScrollManager.initSnapHelper(helper);
}
/**
* 设置页面参数,单位dp
*
* @param pageMargin 默认:0dp
* @param leftPageVisibleWidth 默认:50dp
* @return GalleryRecyclerView
*/
public GalleryRecyclerView initPageParams(int pageMargin, int leftPageVisibleWidth) {
mDecoration.mPageMargin = pageMargin;
mDecoration.mLeftPageVisibleWidth = leftPageVisibleWidth;
return this;
}
/**
* 设置滑动速度(像素/s)
*
* @param speed int
* @return GalleryRecyclerView
*/
public GalleryRecyclerView initFlingSpeed(@IntRange(from = 0) int speed) {
this.mFlingSpeed = speed;
return this;
}
/**
* 设置动画因子
*
* @param factor float
* @return GalleryRecyclerView
*/
public GalleryRecyclerView setAnimFactor(@FloatRange(from = 0f) float factor) {
mAnimManager.setAnimFactor(factor);
return this;
}
/**
* 设置动画类型
*
* @param type int
* @return GalleryRecyclerView
*/
public GalleryRecyclerView setAnimType(int type) {
mAnimManager.setAnimType(type);
return this;
}
/**
* 装载
*
* @return GalleryRecyclerView
*/
public GalleryRecyclerView setUp() {
if (getAdapter().getItemCount() <= 0) {
return this;
}
smoothScrollToPosition(0);
mScrollManager.updateConsume();
return this;
}
public int getOrientation() {
if (getLayoutManager() instanceof LinearLayoutManager) {
if (getLayoutManager() instanceof GridLayoutManager) {
throw new RuntimeException("请设置LayoutManager为LinearLayoutManager");
} else {
return ((LinearLayoutManager) getLayoutManager()).getOrientation();
}
} else {
throw new RuntimeException("请设置LayoutManager为LinearLayoutManager");
}
}
public int getScrolledPosition() {
if (mScrollManager == null) {
return 0;
} else {
return mScrollManager.getPosition();
}
}
@Override
protected Parcelable onSaveInstanceState() {
DLog.w(TAG, "GalleryRecyclerView onSaveInstanceState()");
return super.onSaveInstanceState();
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
// 如果是横竖屏切换(Fragment销毁),不应该走smoothScrollToPosition(0),因为这个方法会导致ScrollManager的onHorizontalScroll不断执行,而ScrollManager.mConsumeX已经重置,会导致这个值紊乱
// 而如果走scrollToPosition(0)方法,则不会导致ScrollManager的onHorizontalScroll执行,所以ScrollManager.mConsumeX这个值不会错误
scrollToPosition(0);
// 但是因为不走ScrollManager的onHorizontalScroll,所以不会执行切换动画,所以就调用smoothScrollBy(int dx, int dy),让item轻微滑动,触发动画
smoothScrollBy(10, 0);
smoothScrollBy(0, 0);
}
/**
* 开始处于的位置
*
* @param i int
* @return GalleryRecyclerView
*/
public GalleryRecyclerView initPosition(@IntRange(from = 0) int i) {
if (i >= getAdapter().getItemCount()) {
i = getAdapter().getItemCount() - 1;
} else if (i < 0) {
i = 0;
}
mInitPos = i;
return this;
}
@Override
public void onItemSizeMeasured(int size) {
if (mInitPos < 0) {
return;
}
if (mInitPos == 0) {
scrollToPosition(0);
} else {
if (getOrientation() == LinearLayoutManager.HORIZONTAL) {
smoothScrollBy(mInitPos * size, 0);
} else {
smoothScrollBy(0, mInitPos * size);
}
}
mInitPos = -1;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
}
implementation 'com.makeramen:roundedimageview:2.3.0'
main
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:gravity="center"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp300"
android:clipChildren="false"
android:orientation="vertical">
<ImageView
android:id="@+id/ivbg"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/dp40"
android:layout_marginTop="@dimen/dp20"
android:layout_marginRight="@dimen/dp40"
android:layout_marginBottom="@dimen/dp20"
android:clipChildren="false" />
</RelativeLayout>
</LinearLayout>
</layout>
item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- android:foreground="?android:attr/selectableItemBackground"-->
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:scaleType="fitXY"
app:riv_border_color="#333333"
app:riv_border_width="2dip"
app:riv_corner_radius="@dimen/dp20"
app:riv_mutate_background="true"
app:riv_oval="false" />
</RelativeLayout>
transform
public class MyAlphaAndScalePageTransformer implements ViewPager.PageTransformer {
final float SCALE_MAX = 0.8F;
final float ALPHA_MAX = 0.5F;
public MyAlphaAndScalePageTransformer() {
}
@Override
public void transformPage(View page, float position) {
float scale = position < 0.0F ? 0.19999999F * position + 1.0F : -0.19999999F * position + 1.0F;
float alpha = position < 0.0F ? 0.5F * position + 1.0F : -0.5F * position + 1.0F;
if (position < 0.0F) {
page.setPivotX((float)page.getWidth());
page.setPivotY((float)(page.getHeight() / 2));
} else {
page.setPivotX(0.0F);
page.setPivotY((float)(page.getHeight() / 2));
}
page.setScaleX(scale);
page.setScaleY(scale);
}
}
adapter
class MyAdapter extends PagerAdapter {
private List<Integer> list;
public MyAdapter(List<Integer> list) {
this.list = list;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View inflate = View.inflate(container.getContext(), R.layout.item_banner, null);
ImageView iv = inflate.findViewById(R.id.iv);
Glide.with(container.getContext())
.load(list.get(position % list.size()))
.into(iv);
container.addView(inflate);
return inflate;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(((View) object));
}
}
main
public class MainActivity extends BaseActivity<ActivityMainBinding> {
private int lastSelect = 1;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initShape() {
}
@Override
protected void initView() {
List<Integer> list = new ArrayList<>();
list.add(R.drawable.bg1);
list.add(R.drawable.bg2);
list.add(R.drawable.bg3);
list.add(R.drawable.bg4);
List<Drawable> listDrawables = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Integer integer = list.get(i % list.size());
Glide.with(mContext)
.asBitmap()
.load(integer)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(22,80)))
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
listDrawables.add(ImageUtils.bitmap2Drawable(resource));
}
});
}
ThreadUtils.executeBySingle(new ThreadUtils.Task<Object>() {
@Override
public Object doInBackground() throws Throwable {
Thread.sleep(500);
return null;
}
@Override
public void onSuccess(Object result) {
mViewBinding.ivbg.setImageDrawable(listDrawables.get(lastSelect));
}
@Override
public void onCancel() {
}
@Override
public void onFail(Throwable t) {
}
});
MyAdapter myAdapter = new MyAdapter(list);
mViewBinding.vp.setOffscreenPageLimit(list.size());
mViewBinding.vp.setAdapter(myAdapter);
mViewBinding.vp.setPageMargin(40);
mViewBinding.vp.setCurrentItem(list.size() * 500 + lastSelect);
mViewBinding.vp.setPageTransformer(false, new MyAlphaAndScalePageTransformer());
mViewBinding.vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
Drawable bitmap = listDrawables.get(position % listDrawables.size());
Drawable lastbitmap = listDrawables.get(lastSelect % listDrawables.size());
Glide.with(mContext)
.load(bitmap)
.transition(DrawableTransitionOptions.withCrossFade(1000))
.apply(new RequestOptions().placeholder(lastbitmap).diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true))
.into(mViewBinding.ivbg);
lastSelect = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
protected void initData() {
}
@Override
protected void initListener() {
}
}
然后是用RecyclerView 实现的 这里可以选择然他一次滑动很多页或者一次滑动一页
List<Integer> list = new ArrayList<>();
list.add(R.drawable.bg1);
list.add(R.drawable.bg2);
list.add(R.drawable.bg3);
list.add(R.drawable.bg4);
List<Drawable> listDrawables = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Integer integer = list.get(i % list.size());
Glide.with(mContext)
.asBitmap()
.load(integer)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(22, 80)))
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
listDrawables.add(ImageUtils.bitmap2Drawable(resource));
}
});
}
ThreadUtils.executeBySingle(new ThreadUtils.Task<Object>() {
@Override
public Object doInBackground() throws Throwable {
Thread.sleep(500);
return null;
}
@Override
public void onSuccess(Object result) {
mViewBinding.ivbg.setImageDrawable(listDrawables.get(lastSelect));
}
@Override
public void onCancel() {
}
@Override
public void onFail(Throwable t) {
}
});
myAdapter = new MyAdapter(R.layout.item_banner, list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
mViewBinding.rv.setAdapter(myAdapter);
mViewBinding.rv.setLayoutManager(linearLayoutManager);
mViewBinding.rv
// 设置滑动速度(像素/s)
.initFlingSpeed(9000)
// 设置页边距和左右图片的可见宽度,单位dp
.initPageParams(0, 40)
// 设置切换动画的参数因子
.setAnimFactor(0.1f)
// 设置切换动画类型,目前有AnimManager.ANIM_BOTTOM_TO_TOP和目前有AnimManager.ANIM_TOP_TO_BOTTOM
.setAnimType(AnimManager.ANIM_BOTTOM_TO_TOP)
// 设置初始化的位置
.initPosition(lastSelect)
// 在设置完成之后,必须调用setUp()方法
.setUp();
// 背景高斯模糊 & 淡入淡出
mViewBinding.rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
final int mCurViewPosition = mViewBinding.rv.getScrolledPosition();
boolean isSamePosAndNotUpdate = (mCurViewPosition == lastSelect);
if (myAdapter == null || mViewBinding.rv == null || isSamePosAndNotUpdate) {
return;
}
mViewBinding.rv.post(new Runnable() {
@Override
public void run() {
Drawable bitmap = listDrawables.get(mCurViewPosition % listDrawables.size());
Drawable lastbitmap = listDrawables.get(lastSelect % listDrawables.size());
Glide.with(mContext)
.load(bitmap)
.transition(DrawableTransitionOptions.withCrossFade(1000))
.apply(new RequestOptions().placeholder(lastbitmap).diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true))
.into(mViewBinding.ivbg);
lastSelect = mCurViewPosition;
}
});
}
}
});
然后是自定义View 这个我是从一个github 改的
public class AnimManager {
public static final int ANIM_BOTTOM_TO_TOP = 0;
public static final int ANIM_TOP_TO_BOTTOM = 1;
/**
* 动画类型
*/
private int mAnimType = ANIM_BOTTOM_TO_TOP;
/**
* 变化因子
*/
private float mAnimFactor = 0.2f;
public void setAnimation(RecyclerView recyclerView, int position, float percent) {
switch (mAnimType) {
case ANIM_BOTTOM_TO_TOP:
setBottomToTopAnim(recyclerView, position, percent);
break;
case ANIM_TOP_TO_BOTTOM:
setTopToBottomAnim(recyclerView, position, percent);
break;
default:
setBottomToTopAnim(recyclerView, position, percent);
break;
}
}
/**
* 从下到上的动画效果
*
* @param recyclerView RecyclerView
* @param position int
* @param percent float
*/
private void setBottomToTopAnim(RecyclerView recyclerView, int position, float percent) {
// 中间页
View mCurView = recyclerView.getLayoutManager().findViewByPosition(position);
// 右边页
View mRightView = recyclerView.getLayoutManager().findViewByPosition(position + 1);
// 左边页
View mLeftView = recyclerView.getLayoutManager().findViewByPosition(position - 1);
// 右右边页
View mRRView = recyclerView.getLayoutManager().findViewByPosition(position + 2);
if (mLeftView != null) {
mLeftView.setScaleX((1 - mAnimFactor) + percent * mAnimFactor);
mLeftView.setScaleY((1 - mAnimFactor) + percent * mAnimFactor);
}
if (mCurView != null) {
mCurView.setScaleX(1 - percent * mAnimFactor);
mCurView.setScaleY(1 - percent * mAnimFactor);
}
if (mRightView != null) {
mRightView.setScaleX((1 - mAnimFactor) + percent * mAnimFactor);
mRightView.setScaleY((1 - mAnimFactor) + percent * mAnimFactor);
}
if (mRRView != null) {
mRRView.setScaleX(1 - percent * mAnimFactor);
mRRView.setScaleY(1 - percent * mAnimFactor);
}
}
/***
* 从上到下的效果
* @param recyclerView RecyclerView
* @param position int
* @param percent int
*/
private void setTopToBottomAnim(RecyclerView recyclerView, int position, float percent) {
// 中间页
View mCurView = recyclerView.getLayoutManager().findViewByPosition(position);
// 右边页
View mRightView = recyclerView.getLayoutManager().findViewByPosition(position + 1);
// 左边页
View mLeftView = recyclerView.getLayoutManager().findViewByPosition(position - 1);
// 左左边页
View mLLView = recyclerView.getLayoutManager().findViewByPosition(position - 2);
if (mLeftView != null) {
mLeftView.setScaleX(1 - percent * mAnimFactor);
mLeftView.setScaleY(1 - percent * mAnimFactor);
}
if (mCurView != null) {
mCurView.setScaleX((1 - mAnimFactor) + percent * mAnimFactor);
mCurView.setScaleY((1 - mAnimFactor) + percent * mAnimFactor);
}
if (mRightView != null) {
mRightView.setScaleX(1 - percent * mAnimFactor);
mRightView.setScaleY(1 - percent * mAnimFactor);
}
if (mLLView != null) {
mLLView.setScaleX((1 - mAnimFactor) + percent * mAnimFactor);
mLLView.setScaleY((1 - mAnimFactor) + percent * mAnimFactor);
}
}
public void setAnimFactor(float mAnimFactor) {
this.mAnimFactor = mAnimFactor;
}
public void setAnimType(int mAnimType) {
this.mAnimType = mAnimType;
}
}
public class MyGalleryItemDecoration extends RecyclerView.ItemDecoration {
private final String TAG = "MainActivity_TAG";
/**
* 每一个页面默认页边距
*/
public int mPageMargin = 0;
/**
* 中间页面左右两边的页面可见部分宽度
*/
public int mLeftPageVisibleWidth = 50;
public int mItemConsumeY = 0;
public int mItemConsumeX = 0;
private OnItemSizeMeasuredListener mOnItemSizeMeasuredListener;
MyGalleryItemDecoration() {
}
@Override
public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
DLog.d(TAG, "GalleryItemDecoration getItemOffset() --> position = " + parent.getChildAdapterPosition(view));
final int position = parent.getChildAdapterPosition(view);
final int itemCount = parent.getAdapter().getItemCount();
parent.post(new Runnable() {
@Override
public void run() {
if (((GalleryRecyclerView) parent).getOrientation() == LinearLayoutManager.HORIZONTAL) {
onSetHorizontalParams(parent, view, position, itemCount);
} else {
onSetVerticalParams(parent, view, position, itemCount);
}
}
});
}
private void onSetVerticalParams(ViewGroup parent, View itemView, int position, int itemCount) {
int itemNewWidth = parent.getWidth();
int itemNewHeight = parent.getHeight() - ConvertUtils.dp2px(4 * mPageMargin + 2 * mLeftPageVisibleWidth);
mItemConsumeY = itemNewHeight +ConvertUtils.dp2px(2 * mPageMargin);
if (mOnItemSizeMeasuredListener != null) {
mOnItemSizeMeasuredListener.onItemSizeMeasured(mItemConsumeY);
}
// 适配第0页和最后一页没有左页面和右页面,让他们保持左边距和右边距和其他项一样
int topMargin = position == 0 ? ConvertUtils.dp2px(mLeftPageVisibleWidth + 2 * mPageMargin) : ConvertUtils.dp2px(mPageMargin);
int bottomMargin = position == itemCount - 1 ? ConvertUtils.dp2px(mLeftPageVisibleWidth + 2 * mPageMargin) : ConvertUtils.dp2px(mPageMargin);
setLayoutParams(itemView, 0, topMargin, 0, bottomMargin, itemNewWidth, itemNewHeight);
}
/**
* 设置水平滚动的参数
*
* @param parent ViewGroup
* @param itemView View
* @param position int
* @param itemCount int
*/
private void onSetHorizontalParams(ViewGroup parent, View itemView, int position, int itemCount) {
int itemNewWidth = parent.getWidth() - ConvertUtils.dp2px(4 * mPageMargin + 2 * mLeftPageVisibleWidth);
int itemNewHeight = parent.getHeight();
mItemConsumeX = itemNewWidth + ConvertUtils.dp2px(2 * mPageMargin);
if (mOnItemSizeMeasuredListener != null) {
mOnItemSizeMeasuredListener.onItemSizeMeasured(mItemConsumeX);
}
DLog.d(TAG, "GalleryItemDecoration onSetHorizontalParams -->" + "parent.width=" + parent.getWidth() + ";mPageMargin=" + ConvertUtils.dp2px(mPageMargin)
+ ";mLeftVis=" + ConvertUtils.dp2px(mLeftPageVisibleWidth) + ";itemNewWidth=" + itemNewWidth);
// 适配第0页和最后一页没有左页面和右页面,让他们保持左边距和右边距和其他项一样
int leftMargin = position == 0 ? ConvertUtils.dp2px(mLeftPageVisibleWidth + 2 * mPageMargin) : ConvertUtils.dp2px(mPageMargin);
int rightMargin = position == itemCount - 1 ? ConvertUtils.dp2px(mLeftPageVisibleWidth + 2 * mPageMargin) : ConvertUtils.dp2px(mPageMargin);
setLayoutParams(itemView, leftMargin, 0, rightMargin, 0, itemNewWidth, itemNewHeight);
}
/**
* 设置参数
*
* @param itemView View
* @param left int
* @param top int
* @param right int
* @param bottom int
* @param itemWidth int
* @param itemHeight int
*/
private void setLayoutParams(View itemView, int left, int top, int right, int bottom, int itemWidth, int itemHeight) {
DLog.d(TAG, "GalleryItemDecoration setLayoutParams -->" + "left=" + left + ";top=" + top
+ ";right=" + right + ";bottom=" + bottom + ";itemWidth=" + itemWidth + ";itemHeight=" + itemHeight);
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
boolean mMarginChange = false;
boolean mWidthChange = false;
boolean mHeightChange = false;
if (lp.leftMargin != left || lp.topMargin != top || lp.rightMargin != right || lp.bottomMargin != bottom) {
lp.setMargins(left, top, right, bottom);
mMarginChange = true;
}
if (lp.width != itemWidth) {
lp.width = itemWidth;
mWidthChange = true;
}
if (lp.height != itemHeight) {
lp.height = itemHeight;
mHeightChange = true;
}
// 因为方法会不断调用,只有在真正变化了之后才调用
if (mWidthChange || mMarginChange || mHeightChange) {
itemView.setLayoutParams(lp);
}
}
public void setOnItemSizeMeasuredListener(OnItemSizeMeasuredListener itemSizeMeasuredListener) {
this.mOnItemSizeMeasuredListener = itemSizeMeasuredListener;
}
interface OnItemSizeMeasuredListener {
/**
* Item的大小测量完成
* @param size int
*/
void onItemSizeMeasured(int size);
}
}
public class MyScrollManager {
private static final String TAG = "MainActivity_TAG";
private GalleryRecyclerView mGalleryRecyclerView;
private int mPosition = 0;
/**
* x方向消耗距离,使偏移量为左边距 + 左边Item的可视部分宽度
*/
private int mConsumeX = 0;
private int mConsumeY = 0;
MyScrollManager(GalleryRecyclerView mGalleryRecyclerView) {
this.mGalleryRecyclerView = mGalleryRecyclerView;
}
/**
* 初始化SnapHelper
*
* @param helper int
*/
public void initSnapHelper(int helper) {
switch (helper) {
case GalleryRecyclerView.LINEAR_SNAP_HELPER:
LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();
mLinearSnapHelper.attachToRecyclerView(mGalleryRecyclerView);
break;
case GalleryRecyclerView.PAGER_SNAP_HELPER:
PagerSnapHelper mPagerSnapHelper = new PagerSnapHelper();
mPagerSnapHelper.attachToRecyclerView(mGalleryRecyclerView);
break;
default:
break;
}
}
/**
* 监听RecyclerView的滑动
*/
public void initScrollListener() {
GalleryScrollerListener mScrollerListener = new GalleryScrollerListener();
mGalleryRecyclerView.addOnScrollListener(mScrollerListener);
}
public void updateConsume() {
mConsumeX += OsUtil.dpToPx(mGalleryRecyclerView.getDecoration().mLeftPageVisibleWidth + mGalleryRecyclerView.getDecoration().mPageMargin * 2);
mConsumeY += OsUtil.dpToPx(mGalleryRecyclerView.getDecoration().mLeftPageVisibleWidth + mGalleryRecyclerView.getDecoration().mPageMargin * 2);
DLog.d(TAG, "ScrollManager updateConsume mConsumeX=" + mConsumeX);
}
class GalleryScrollerListener extends RecyclerView.OnScrollListener {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
DLog.d(TAG, "ScrollManager newState=" + newState);
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mGalleryRecyclerView.getOrientation() == LinearLayoutManager.HORIZONTAL) {
onHorizontalScroll(recyclerView, dx);
} else {
onVerticalScroll(recyclerView, dy);
}
}
}
/**
* 垂直滑动
*
* @param recyclerView RecyclerView
* @param dy int
*/
private void onVerticalScroll(final RecyclerView recyclerView, int dy) {
mConsumeY += dy;
// 让RecyclerView测绘完成后再调用,避免GalleryAdapterHelper.mItemHeight的值拿不到
recyclerView.post(new Runnable() {
@Override
public void run() {
int shouldConsumeY = mGalleryRecyclerView.getDecoration().mItemConsumeY;
// 位置浮点值(即总消耗距离 / 每一页理论消耗距离 = 一个浮点型的位置值)
float offset = (float) mConsumeY / (float) shouldConsumeY;
// 获取当前页移动的百分值
float percent = offset - ((int) offset);
mPosition = (int) offset;
DLog.i(TAG, "ScrollManager offset=" + offset + "; mConsumeY=" + mConsumeY + "; shouldConsumeY=" + mPosition);
// 设置动画变化
mGalleryRecyclerView.getAnimManager().setAnimation(recyclerView, mPosition, percent);
}
});
}
/**
* 水平滑动
*
* @param recyclerView RecyclerView
* @param dx int
*/
private void onHorizontalScroll(final RecyclerView recyclerView, final int dx) {
mConsumeX += dx;
// 让RecyclerView测绘完成后再调用,避免GalleryAdapterHelper.mItemWidth的值拿不到
recyclerView.post(new Runnable() {
@Override
public void run() {
int shouldConsumeX = mGalleryRecyclerView.getDecoration().mItemConsumeX;
// 位置浮点值(即总消耗距离 / 每一页理论消耗距离 = 一个浮点型的位置值)
float offset = (float) mConsumeX / (float) shouldConsumeX;
// 获取当前页移动的百分值
float percent = offset - ((int) offset);
mPosition = (int) offset;
DLog.i(TAG, "ScrollManager offset=" + offset + "; percent=" + percent + "; mConsumeX=" + mConsumeX + "; shouldConsumeX=" + shouldConsumeX + "; position=" + mPosition);
// 设置动画变化
mGalleryRecyclerView.getAnimManager().setAnimation(recyclerView, mPosition, percent);
}
});
}
public int getPosition() {
return mPosition;
}
}