当前位置: 首页 > 知识库问答 >
问题:

RecyclerView和SwipeRefreshLayout

晋坚
2023-03-14

我在SwipeRefreshLayout中使用了新的回收视图布局,遇到了一个奇怪的行为。当将列表滚动回顶部时,有时顶部的视图会被打断。

如果我现在尝试滚动到顶部,将触发拉刷新。

如果我尝试删除回收器视图周围的滑动刷新布局,问题就会消失。并且可以在任何手机上复制(不仅仅是L-Preview设备)。

 <android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/contentView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="gone">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/hot_fragment_recycler"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>

这就是我的布局——行是由RecycleServiceAdapter(此列表中有2种视图类型)动态构建的。

public class HotRecyclerAdapter extends TikDaggerRecyclerAdapter<GameRow> {

private static final int VIEWTYPE_GAME_TITLE = 0;
private static final int VIEWTYPE_GAME_TEAM = 1;

@Inject
Picasso picasso;

public HotRecyclerAdapter(Injector injector) {
    super(injector);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position, int viewType) {
    switch (viewType) {
        case VIEWTYPE_GAME_TITLE: {
            TitleGameRowViewHolder holder = (TitleGameRowViewHolder) viewHolder;
            holder.bindGameRow(picasso, getItem(position));
            break;
        }
        case VIEWTYPE_GAME_TEAM: {
            TeamGameRowViewHolder holder = (TeamGameRowViewHolder) viewHolder;
            holder.bindGameRow(picasso, getItem(position));
            break;
        }
    }
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    switch (viewType) {
        case VIEWTYPE_GAME_TITLE: {
            View view = inflater.inflate(R.layout.game_row_title, viewGroup, false);
            return new TitleGameRowViewHolder(view);
        }
        case VIEWTYPE_GAME_TEAM: {
            View view = inflater.inflate(R.layout.game_row_team, viewGroup, false);
            return new TeamGameRowViewHolder(view);
        }
    }
    return null;
}

@Override
public int getItemViewType(int position) {
    GameRow row = getItem(position);
    if (row.isTeamGameRow()) {
        return VIEWTYPE_GAME_TEAM;
    }
    return VIEWTYPE_GAME_TITLE;
}

这是适配器。

   hotAdapter = new HotRecyclerAdapter(this);

    recyclerView.setHasFixedSize(false);
    recyclerView.setAdapter(hotAdapter);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    contentView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            loadData();
        }
    });

    TypedArray colorSheme = getResources().obtainTypedArray(R.array.main_refresh_sheme);
    contentView.setColorSchemeResources(colorSheme.getResourceId(0, -1), colorSheme.getResourceId(1, -1), colorSheme.getResourceId(2, -1), colorSheme.getResourceId(3, -1));

以及包含回收器和SwipeRefreshLayout的片段的代码。

是否有其他人经历过这种行为并解决了它,或者至少找到了它的原因?

共有3个答案

冀萧迟
2023-03-14

我最近遇到了同样的问题。我尝试了@Krunal\u Patel建议的方法,但它在我的Nexus 4中大部分时间都有效,在三星galaxy s2中根本不起作用。调试时,请单击recyclerView。getChildAt(0)。getTop()对于RecyclerView总是不正确的。因此,在研究了各种方法之后,我认为我们可以利用LayoutManager的findFirstCompletelyVisibleItemPosition()方法来预测RecyclerView的第一个项目是否可见,以启用SwipeRefreshLayout。找到下面的代码。希望它能帮助尝试解决相同问题的人。干杯

    recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        }

        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            swipeRefresh.setEnabled(linearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0);
        }
    });
陶沛
2023-03-14

<罢工> 在您使用此解决方案之前:回收器视图还没有完成,尽量不要在生产中使用它,除非你像我一样!

截至2014年11月,RecyclerView中仍存在漏洞,可能导致CanScrollVertical过早返回false。此解决方案将解决所有滚动问题。

插入式解决方案:

public class FixedRecyclerView extends RecyclerView {
    public FixedRecyclerView(Context context) {
        super(context);
    }

    public FixedRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FixedRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean canScrollVertically(int direction) {
        // check if scrolling up
        if (direction < 1) {
            boolean original = super.canScrollVertically(direction);
            return !original && getChildAt(0) != null && getChildAt(0).getTop() < 0 || original;
        }
        return super.canScrollVertically(direction);

    }
}

您甚至不需要将代码中的RecyclView替换为FixedRecyclView,替换XML标签就足够了!(确保当RecyclView完成时,过渡将快速简单)

解释:

基本上,canScroll垂直(boolean)过早返回false,因此我们检查RecyclView是否一直滚动到第一个视图的顶部(其中第一个子视图的顶部为0),然后返回。

编辑:如果出于某种原因不想扩展RecyclerView,可以扩展SwipeRefreshLayout并重写canChildScrollUp()方法,并将检查逻辑放在其中。

编辑2:

诸超
2023-03-14

在回收视图的addOnScrollListener中编写以下代码

像这样:

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            int topRowVerticalPosition =
                    (recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
            swipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0);

        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }
    });
 类似资料:
  • 我正在使用和实现一个刷卡删除。在我的函数中,我调用我的服务来删除带有API请求的元素,但为此我需要适配器给我元素的id。我重写了适配器的函数 但是,当我使用它在我的函数 我在行中遇到一个错误 虽然应该返回一个int:/

  • 我正在使用Glide在我的应用程序中加载图像,我正在使用它来显示一些图像中的回收人员视图项目。 这是我的适配器回收器视图: 一切都很好,除了当项目从窗口分离时,或者更好地说,当项目不可见时,位图或ImageViews的Drawable不会从内存中删除。 在滚动1分钟后,我的内存出现异常。 如您所见,我正在使用<code>Glide。clear()方法解决此问题,但它不起作用。 关于这个问题的任何建

  • 简要说明:我对java或android studio不是很有经验,所以请直接回答我的noobish问题。 我正在做一个有RAL颜色片段的项目。总共只有280多张图片。我正在尝试为此片段创建一个recyclerView。为了避免这个问题比实际问题长出几英里,我删去了ralfragment中的一些颜色。 我希望颜色的布局如下所示: 我看了一些教程(没有一个是在片段中使用rv的),并试图将它们实现到我的

  • 问题内容: 我一直在尝试使用此处的少量指导,使用RecyclerView实现CollapsingToolbar:http : //android-developers.blogspot.co.uk/2015/05/android-design-support- library.html 和项目此处:https : //github.com/chrisbanes/cheesesquare,我目前具有

  • 关于 RecyclerView 集成库使你在你的应用中能够使用 RecyclerViewPreloader ,它可以在用户滑动 RecyclerView 时自动加载稍微超前一些的图片。 配合使用正确的图片尺寸和高效率的磁盘缓存策略,这个库可以显著减少用户滑动图片列表时看到的加载指示器的数量。 Gradle 依赖 要使用 RecyclerView 集成库,在你的 build.gradle 文件中添加

  • 描述 动态 View 的滚动组件,用于大量数据列表场景。在 Weex 下是对 list 与 cell 的包装,它通过内部子组件复用提升了滚动列表的性能。 安装 $ npm install rax-recyclerview --save 属性 属性 类型 默认值 必填 描述 支持 onEndReachedThreshold number 500 ✘ 设置加载更多的偏移 onEndReached fu