RecyclerView 滚动到指定position,并置顶

来源:互联网 发布:淘宝怎么进行实名认证 编辑:程序博客网 时间:2024/04/30 21:11

今天写页面有一个需求是这样的:
有一个广告条,显示2条广告信息并且,可以自动向上滚动。what? 2条看得我懵逼,一般我们看到的广告条都是一条一条切换,使用ViewFlipper就能够实现,但ViewFlipper不能显示2条。苦思冥想下,觉得使用RecyclerView来实现。
使用RecyclerView实现广告条需要实现以下功能:

1.RecyclerView不能响应用户的滑动事件,但item需要响应用户的点击事件.
2.自动向上滚动,并且第一条可见item需要刚好置顶

现在我们一条一条来解决问题:
1.关于第一条,我们只需重写RecyclerView的触摸拦截和分发事件,全部返回为false,就可以不响应滑动事件且item可以响应点击事件。

public class AdvertiseRecyclerView extends RecyclerView {    public AdvertiseRecyclerView(Context context) {        super(context);    }    public AdvertiseRecyclerView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public AdvertiseRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent e) {        return false;    }    @Override    public boolean onTouchEvent(MotionEvent e) {        return false;    }}

2.RecyclerView滚动的方法有

  1. smoothScrollBy();
  2. smoothScrollToPosition()
  3. scrollTo();
  4. scrollBy();
    其中带有smooth的方法为带有滚动动画效果的方法。我们发现满足我们要求的就只有smoothScrollToPosition()方法。但是smoothScrollToPosition()只能将我指定的position的item显示在界面上,但不能将其置顶。我们查看RecyclerView的smoothScrollToPosition()方法源码如下:
 public void smoothScrollToPosition(int position) {        if (mLayoutFrozen) {            return;        }        if (mLayout == null) {            Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. "                    + "Call setLayoutManager with a non-null argument.");            return;        }        mLayout.smoothScrollToPosition(this, mState, position);    }

我们可以看到RecyclerView的滑动实际是调用了LayoutManager的滑动方法。
我们查看LinearLayoutManager的smoothScrollToPosition()方法:

@Override    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,            int position) {        LinearSmoothScroller linearSmoothScroller =                new LinearSmoothScroller(recyclerView.getContext());        linearSmoothScroller.setTargetPosition(position);        startSmoothScroll(linearSmoothScroller);    }

发现LinearLayoutManager的smoothScrollToPosition()方法中new 了一个LinearSmoothScroller 的东西来控制其滑动,我们重写LinearSmoothScroller :

 class AdvertiseLinearSmoothScroller extends LinearSmoothScroller{        public AdvertiseLinearSmoothScroller(Context context) {            super(context);        }        /**         *         * @param viewStart RecyclerView的top位置         * @param viewEnd RecyclerView的Bottom位置         * @param boxStart item的top位置         * @param boxEnd  item的bottom位置         * @param snapPreference 滑动方向的识别         * @return         */        @Override        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {            return boxStart-viewStart;//返回的就是我们item置顶需要的偏移量        }        /**         * 此方法返回滚动每1px需要的时间,可以用来控制滚动速度         * 即如果返回2ms,则每滚动1000px,需要2秒钟         * @param displayMetrics         * @return         */        @Override        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {            return super.calculateSpeedPerPixel(displayMetrics);        }    }

我们重写calculateDtToFit()方法,即可实现smoothScrollToPosition()使item自动置顶功能.
使用AdvertiseLinearSmoothScroller 重写LinearLayoutManager

public class AdvertiseLinearLayoutManager extends LinearLayoutManager {    public AdvertiseLinearLayoutManager(Context context) {        super(context);    }    public AdvertiseLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {        super(context, orientation, reverseLayout);    }    public AdvertiseLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {        AdvertiseLinearSmoothScroller linearSmoothScroller =                new AdvertiseLinearSmoothScroller(recyclerView.getContext());        linearSmoothScroller.setTargetPosition(position);        startSmoothScroll(linearSmoothScroller);    }}

然后我们使用定时器每秒使recyclerView滚动到position+1的位置即可实现需求.

原创粉丝点击