片段作为RecyclerView的ViewHolder?

时间:2016-03-16 21:07:32

标签: android android-fragments android-recyclerview

如何创建一个ViewHolder儿童实际上是碎片的RecyclerView?

当前示例(不起作用,视图堆叠在彼此之上)

这是片段的onResume(),它是Activity

的主要内容
// onResume() in FragmentA (main content of an Activity)
recyclerView.addItemDecoration(new VerticalSpaceItemDecoration(5));
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
List<Fragment> fragments = new LinkedList<>();
fragments.add(FeaturedRecyclerFragment.newInstance(R.string.recycler_title_featured));
fragments.add(TrendingRecyclerFragment.newInstance(R.string.recycler_title_trending));
FeedsAdapter recyclerAdapter = new FeedsAdapter(getContext(), getFragmentManager(), fragments);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerAdapter);

这是RecyclerView适配器代码:

public class FeedsAdapter extends RecyclerView.Adapter<FeedsAdapter.FeedsViewHolder> {

    private static final String TAG = FeedsAdapter.class.getSimpleName();

    private final Context context;
    private FragmentManager fragmentManager;
    private final List<Fragment> fragments;

    public FeedsAdapter(Context context, FragmentManager fragmentManager, List<Fragment> fragments) {
        this.context = context;
        this.fragmentManager = fragmentManager;
        this.fragments = fragments;
    }

    @Override
    public FeedsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d(TAG, "onCreateViewHolder()");
        View itemView = LayoutInflater.from(context).inflate(R.layout.feeds_view_holder, parent, false);
        return new FeedsViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(FeedsViewHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder() " + position);
        if (fragmentManager == null) {
            throw new IllegalArgumentException("LoaderManager null, cannot bind view holder");
        }

        Fragment fragment = fragments.get(position);
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(holder.itemView.getId(), fragment, TAG + "pos" + position);
        transaction.commit();
    }

    @Override
    public int getItemCount() {
        Log.d(TAG, "getItemCount()");
        return fragments.size();
    }

    static class FeedsViewHolder extends RecyclerView.ViewHolder {

        public FeedsViewHolder(View itemView) {
            super(itemView);
        }
    }
}

最后,这是在FeedsAdapter中膨胀的feeds_view_holder布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/recycler_fragment_container">

</FrameLayout>

基本上问题是RecyclerView没有以预期的方式加载它的子节点(ViewHolders)。他们在彼此之上。我希望RecyclerView将片段加载为视图而不是绑定的典型视图。这甚至可能吗?我想我可以放弃RecyclerView,但加载的内容是相当动态的(例如,有一个“最喜欢的供稿”部分,但如果你没有任何收藏,那么它不会显示)。当我使用带有RecyclerViews的ViewHolder孩子的RecyclerView时,事情进展顺利,但我想尽可能使用片段。

2 个答案:

答案 0 :(得分:4)

这不是一个好主意。

由于您没有在当前设计中回收或删除片段,因此最好在ScrollView周围使用片段加载到的LinearLayout。这些碎片的装载时间比使用RecyclerView要快一些,但是你不必打击那些你没有利用的回收基础设施。

片段被加载到彼此之上,因为当您提交事务时,您实际上并未更改视图。你告诉片段管理器,“嘿,当你有机会将这个片段连接到这个ViewGroup ID?”片段管理器会找到它找到的那个视图ID的第一个实例,因此它们会相互加载。

您可以通过为不同的职位设置不同的ID来解决这个问题,但我不建议这样做。

答案 1 :(得分:0)

尝试将根视图组从framelayout更改为线性布局,以阻止视图相互绘制。