RecyclerView实现纵向导航栏(获取RecyclerView第一个View)

预览

预览

思路

纵向的RecyclerView完全没有难度,主要是指示器(IndicatorView)的动画,下面主要说IndicatorView的实现
1. TranslationY动画:由初始位置滑动到点击的当前位置

ObjectAnimator animator = ObjectAnimator.ofFloat(this, "TranslationY", oldY, newY);
        animator.setDuration(500);
        animator.setInterpolator(new OvershootInterpolator());
        animator.start();
  1. 获取当前位置:RecyclerView点击的时候可以获取当前点击的View,有View就可以拿到位置信息。
  2. 获取初始位置,就是第0个View的位置。如果只是简单的recyclerView.getLayoutManager().findViewByPosition(0),得到的View=null,尴尬不?
    这是因为在获取的时候RecyclerView并没有加载完成,所以这个问题就转换成了RecyclerView什么时候加载完成。这就好说了吧,代码如下。
recyclerView.post(new Runnable() {
            @Override
            public void run() {
            }
        });

计算滑动距离

private float calculateViewCenter(View view) {
        int tabHeight = getMeasuredHeight();
        int viewHeight = view.getHeight();
        int viewTop = view.getTop();
        return 1f * (viewTop + viewHeight / 2 - tabHeight / 2);
    }

Activity代码

recyclerView.post(new Runnable() {
            @Override
            public void run() {
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        View child = manager.findViewByPosition(0);
                        if (child != null) {
                            indicatorView.openAnimator(child);
                        }
                    }
                });
            }
        });

代码

下载代码
下载的代码中有一部分有错,需要自己更改一下。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RecyclerView纵向自动滚动实现可以使用 RecyclerView 自带的 LayoutManager 或者自定义 LayoutManager 实现。 使用 RecyclerView 自带的 LayoutManager 实现纵向自动滚动: 1. 获取 RecyclerView 的 LinearLayoutManager 对象 2. 创建一个 Handler 对象和一个 Runnable 对象 3. 在 Runnable 的 run() 方法中,调用 LinearLayoutManager 的 smoothScrollToPosition() 方法实现自动滚动 4. 在 Handler 中使用 postDelayed() 方法,指定延迟时间和 Runnable 对象,实现定时滚动。 示例代码如下: ``` private LinearLayoutManager mLinearLayoutManager; private Handler mHandler = new Handler(); private Runnable mRunnable = new Runnable() { @Override public void run() { int currentPos = mLinearLayoutManager.findFirstVisibleItemPosition(); mLinearLayoutManager.smoothScrollToPosition(mRecyclerView, null, currentPos + 1); mHandler.postDelayed(this, 3000); // 延迟 3 秒滚动 } }; private void initRecyclerView() { mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); mRecyclerView.setLayoutManager(mLinearLayoutManager); mRecyclerView.setAdapter(mAdapter); } private void startAutoScroll() { mHandler.postDelayed(mRunnable, 3000); // 延迟 3 秒滚动 } private void stopAutoScroll() { mHandler.removeCallbacks(mRunnable); } ``` 使用自定义 LayoutManager 实现纵向自动滚动: 1. 自定义一个继承自 LinearLayoutManager 的 LayoutManager 2. 在 LayoutManager 的 onLayoutChildren() 方法中,调用 super.onLayoutChildren() 方法完成布局,并获取第一个和最后一个可见 item 的位置 3. 在 LayoutManager 的 scrollVerticallyBy() 方法中,判断当前滑动的距离是否大于等于一个屏幕的高度,如果是,则调用 scrollToPosition() 方法实现自动滚动。 示例代码如下: ``` public class AutoScrollLayoutManager extends LinearLayoutManager { private int mScreenHeight; public AutoScrollLayoutManager(Context context) { super(context); mScreenHeight = context.getResources().getDisplayMetrics().heightPixels; } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { super.onLayoutChildren(recycler, state); int firstVisiblePos = findFirstVisibleItemPosition(); int lastVisiblePos = findLastVisibleItemPosition(); if (lastVisiblePos - firstVisiblePos < state.getItemCount() - 1) { // 如果可见 item 数量小于总 item 数量,强制重新布局 detachAndScrapAttachedViews(recycler); layoutChildren(recycler, state); } } private void layoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { int offsetY = 0; for (int i = 0; i < getItemCount(); i++) { View view = recycler.getViewForPosition(i); addView(view); measureChildWithMargins(view, 0, 0); int width = getDecoratedMeasuredWidth(view); int height = getDecoratedMeasuredHeight(view); layoutDecorated(view, 0, offsetY, width, offsetY + height); offsetY += height; } } @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { int travel = dy; if (dy > 0) { // 手指向上滑动 View lastVisibleView = getChildAt(getChildCount() - 1); int lastVisiblePos = getPosition(lastVisibleView); if (lastVisibleView.getBottom() - dy < mScreenHeight) { // 如果最后一个可见 item 没有完全显示,就不滑动 travel = 0; } else if (lastVisiblePos == getItemCount() - 1) { // 如果滑到最后一个 item,就不滑动 travel = 0; } } int realScroll = super.scrollVerticallyBy(travel, recycler, state); if (realScroll != travel) { // 如果滑动距离小于手指滑动距离,说明已经滑到边界了,就自动滚动 int currentPos = findFirstVisibleItemPosition(); scrollToPosition(currentPos + 1); } return realScroll; } } ``` 使用自定义的 AutoScrollLayoutManager: ``` private AutoScrollLayoutManager mLayoutManager; private void initRecyclerView() { mLayoutManager = new AutoScrollLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(mAdapter); } private void startAutoScroll() { mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1); // 先滚动到最后一个 item mHandler.postDelayed(mRunnable, 3000); // 延迟 3 秒开始自动滚动 } private void stopAutoScroll() { mHandler.removeCallbacks(mRunnable); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值