安卓项目实战之:RecyclerView实现中奖公告列表信息垂直自动无限滚动效果
效果图

录的屏滑动有点卡,其实还是很丝滑的。
(半夜三点钟还在写博客,只希望这个系列博客可以帮助到更多人,后期还会一直更新,欢迎大家评论点赞,你们的支持是我永远的动力,嘿嘿。)
实现的思路
通过调用RecyclerView的smoothScrollToPosition(int position)方法我们可以实现平滑的滚动到参数所指定的position的位置,如果仅仅是调用了该方法那么滚动将会以系统默认的速度来进行,并且该速度通常是非常快的,快到如果将参数position的值设置的很小可能会看不到滚动的过程而直接看到结果,设置稍微大点例如为100时就会看到2秒的滚动效果,值越大滚动过程持续的时间越长,并且执行该方法滚动到该位置之后会立刻停止滚动,我们本篇文章讲的是RecyclerView如何实现自动无限滚动效果,因此我们可以这么来实现:
1,设置RecyclerView的item数量为int类型的最大值,这样滚动过程就会持续很长时间,会给用户造成一种错觉是无限滚动,其实也是单次的,等到滚动到int最大值指定的那个位置就会停止,但是一般用户不可能等那么长时间,如果不放心我们也可以在代码中设置实现循环滚动,
2,解决滚动速度的问题,前面说了,系统默认的滚动速度是非常快的,可能一秒钟就滚动过了几十个item甚至接近一百个item,滚动太快致使item内容在滚动过程中完全看不清楚,显然我们需求肯定不是这样的,我们要实现item的缓慢自动滚动,并且在滚动过程中要能清楚的看到每个item的内容,那么我们就需要改变系统默认的滚动速度,做法是自定义一个LayoutManager类继承LinearLayoutManager,然后复写smoothScrollToPosition方法。在该方法中创建一个Scroller对象,在Scroller对象中再重写calculateSpeedPerPixel(DisplaMetrics)方法,该方法就是用来控制滚动速度的,具体请看下面代码示例。
1,布局文件很简单就是定义了一个RecyclerView,MainActivity代码如下:
public class MainActivity extends AppCompatActivity {AutoScrollRecyclerView recyclerView;private List<String> list = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recyclerView);for(int i=0;i<30;i++){list.add("我是条目"+i);}LinearLayoutManager manager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
// AutoScrollLayoutManager manager = new AutoScrollLayoutManager(this,LinearLayoutManager.VERTICAL,false);recyclerView.setLayoutManager(manager);// 设置适配器Adapter mAdapter = new Adapter(this, list);recyclerView.setAdapter(mAdapter);// 调用该方法来触发自动滚动recyclerView.smoothScrollToPosition(mAdapter.getItemCount());}class Adapter extends RecyclerView.Adapter<MainActivity.ViewHolder> {private Context context;private List<String> list;public Adapter(Context context, List<String> list) {this.context = context;this.list = list;}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_recycler, parent, false));}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {if(!list.isEmpty()){// 因为getItemCount返回int最大值,而我们设置的数据不可能那么多,所以在为item绑定数据的时候,我们// 这里采用取余的方法,这样就能保证每一项item都是有值的,但为了不重复就要求我们的样本数据多一点holder.vText.setText(list.get(position%list.size()));}}@Overridepublic int getItemCount() {// 返回int最大值return list == null ? 0 : Integer.MAX_VALUE;}}class ViewHolder extends RecyclerView.ViewHolder {TextView vText;public ViewHolder(View itemView) {super(itemView);vText = itemView.findViewById(R.id.tv);}}}
注意上面getItemCount和onBindViewHolder方法在定义时的小技巧,上面注释也已经写的很清楚了。
运行程序会发现此时自动滚动已经实现了,但是滚动速度还没处理,还是系统默认的,所以非常快,几乎看不到条目内容,接下来我们来处理滚动的速度,方法如下:
自定义一个类AutoScrollLayoutManager继承LinearLayoutManager,然后复写smoothScrollToPosition方法。在该方法中创建一个Scroller对象,在Scroller对象中再重写calculateSpeedPerPixel(DisplaMetrics)方法,代码如下:
public class AutoScrollLayoutManager extends LinearLayoutManager {public AutoScrollLayoutManager(Context context) {super(context);}public AutoScrollLayoutManager(Context context, int orientation, boolean reverseLayout) {super(context, orientation, reverseLayout);}public AutoScrollLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}// 修改系统默认的滚动速度需要实现该方法;@Overridepublic void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, intposition) {LinearSmoothScroller linearSmoothScroller =new LinearSmoothScroller(recyclerView.getContext()) {@Nullable@Overridepublic PointF computeScrollVectorForPosition(int targetPosition) {return AutoScrollLayoutManager.this.computeScrollVectorForPosition(targetPosition);}@Overrideprotected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {// 计算滑动每个像素需要的时间,这里应该与屏幕适配;return 15f / displayMetrics.density;}};linearSmoothScroller.setTargetPosition(position);startSmoothScroll(linearSmoothScroller);}}
然后在创建布局管理器时,使用我们自定义的AutoScrollLayoutManager,此时再运行应用我们会发现现在速度已经慢了好多了,条目内容也可以看得清楚了。
但是还有个问题就是当RecyclerView在自动滚动过程中当我们用手触摸到了,它就会立刻停止滚动,并且它还能响应我们的滑动事件,而大多数时候需求仅仅是自动滚动展示数据而已,要求屏蔽我们的触摸和滑动动作,那么此时我们就需要自定义RecyclerView,重写两个与事件相关的方法,代码如下示例:
public class AutoScrollRecyclerView extends RecyclerView {public AutoScrollRecyclerView(Context context) {super(context);}public AutoScrollRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public AutoScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}// 拦截事件;@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {// 拦截触摸事件;return true;}@Overridepublic boolean onTouchEvent(MotionEvent e) {// 消费事件;return true;}}
至此再运行代码,效果基本上已经能够满足需求了,前面也分析过看似无限滑动其实也只是一种错觉,是我们将条目总数设置的很大(int的最大值)将滚动速度设置的很小给用户造成的错觉,其实本质还是单次滚动,滚动到int最大值的位置还是会停止,为了实现真正意义上的无限滚动,我们可以通过监听RecyclerView的滑动状态来实现循环滚动,即当滚动到最后一个item时,再次重新定位到开始位置,然后再次滑动到最后一个item,依次循环,代码如下例:
this.setOnScrollListener(new OnScrollListener() {@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);if (newState == RecyclerView.SCROLL_STATE_IDLE) {// 如果自动滑动到最后一个位置,则此处状态为SCROLL_STATE_IDLEAutoScrollLayoutManager lm = (AutoScrollLayoutManager) recyclerView.getLayoutManager();int position = lm.findLastCompletelyVisibleItemPosition();int count = lm.getItemCount();if(position == count-1){lm.scrollToPosition(0);AutoScrollRecyclerView.this.smoothScrollToPosition(mAdapter.getItemCount());}}}});
至此就实现了列表自动无限滚动效果。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
