Android RecyclerView在同一位置显示多个项目

时间:2017-05-23 20:46:15

标签: android android-recyclerview

我在RecyclerView类中发生了许多奇怪的事情,我认为这些事情都是连接起来的。首先,这是我的实施:

onCreateViewHolder

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    padding = parent.getResources().getDimensionPixelSize(R.dimen.rec_padding);

    switch (viewType) {

        case USER:

            View userView = inflater.inflate(R.layout.user_view, parent, false);
            return new UserViewHolder(userView);

        case POST:

            View postView = inflater.inflate(R.layout.post_view, parent, false);
            return new PostViewHolder(postView);

        default:

            return null;
    }
}

onBindViewHolder

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    switch (holder.getItemViewType()) {

        case USER:

            UserViewHolder userViewHolder = (UserViewHolder) holder;
            User user = (User) items.get(position);

            if (position == 0) {

                userViewHolder.recCard.setPadding(0, padding, 0, 0);
            }

            //Get relevant date for user

            if (user.getExpanded()) {

                userViewHolder.details.setVisibility(View.VISIBLE);
            }

            userViewHolder.showDetails.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View view) {

                    if (userViewHolder.details.getVisibility() != View.VISIBLE) {

                        userViewHolder.details.setVisibility(View.VISIBLE);
                        user.setExpanded(true);
                    } else {

                        userViewHolder.details.setVisibility(View.GONE);
                        user.setExpanded(false);
                    }
                }
            });

            break;

        case POST:

            PostViewHolder postViewHolder = (PostViewHolder) holder;
            Post post = (Post) items.get(position);

            if (position == 0) {

                postViewHolder.recCard.setPadding(0, padding, 0, 0);
            }

            //Get relevant date for post

            break;
    }
}

所以我遇到的问题:

1)我将padding添加到列表中第一项的顶部。这对于第一个项目正如预期的那样工作。但是,一旦我开始滚动,填充最终会添加到列表中其他项的顶部。我的假设是,一旦我到达项目列表中的某个点,新项目就位于0位置,所以它也会得到额外的填充。

2)我正在尝试保存RecyclerView中每个项目的某些属性,特别是它们是否被扩展。我这样做是通过将扩展状态作为布尔值存储在对象本身中,然后在onBindViewHolder内检索它。这不起作用 - 与上面类似,列表中的其他项目也会在我滚动时显示为展开。因此,扩展状态不能正确保存。

2 个答案:

答案 0 :(得分:1)

首先,从适配器中删除所有填充代码。你正在寻找ItemDecoration

其次,在UserHolder中设置您的onclick,这样您将只有一个实例用于所有用户视图。

其他用户帖子也会展开,因为您没有在其他地方写入隐藏详细信息的状态。这个组件称为recyclerview是有原因的。您创建一次并越来越多地使用相同的视图。所以每次它被回收(需要显示的地方)都会调用onbind方法。它被以前的状态所吸引..

答案是肯定的,所有这些错误都依赖于同样的错误。来自Java Best Practices;每个if状态都应该有一个else状态。

PS:这是可选的,但我会在recyclerview中使用recyclerview来实现帖子和扩展用户视图。您可以更改用于填充帖子的内部回收站视图的可见性(也许您在我看不到您的持有者类时这样做了)

祝你好运

埃姆雷

答案 1 :(得分:1)

第一个问题:

  

1)我将padding添加到列表中第一项的顶部。   这对于第一个项目正如预期的那样工作。但是,一旦我开始   滚动填充最终会添加到其他项目的顶部   列表。我的假设是,一旦我达到某一点   项目列表,新项目位于0位置,因此它也获得了额外的项目   填充。

开始滚动后,第0个项目显示的视图将被回收。你需要以某种方式将它的填充重置为原始状态。快速简便的方法是将这样的东西添加到你的onBindViewHolder:

if (position == 0) {
  userViewHolder.recCard.setPadding(0, padding, 0, 0);
} else {
  userViewHolder.recCard.setPadding(0, 0, 0, 0);
}

更好,更合适的方法是使用上面评论中提到的ItemDecoration。它并不太复杂,可能会使您的代码更清晰。

对于你的第二个问题:

  

2)我正在尝试保存关于每个项目的某些属性   RecyclerView,特别是它们是否被扩展。我是   通过将扩展状态作为布尔值存储在对象中来实现   本身,然后在onBindViewHolder中检索它。这不是   工作虽然 - 类似于上面,列表中的其他项目也是   滚动后显示为扩展。所以扩张的状态不是   妥善保存。

与第一个问题类似,您的展开式视图会被回收,而任何选择它们的人都不会将视图状态恢复为未展开状态。你可以添加这样的东西:

if (user.getExpanded()) {
  userViewHolder.details.setVisibility(View.VISIBLE);
} else {
  // do whatever to restore view state into non-expanded
  userViewHolder.details.setVisibility(View.GONE);
}