嵌套的RecyclerViews,内部回收器不显示

时间:2019-04-08 10:13:33

标签: android android-recyclerview nested

我有一个应用程序,可以将图片发送到我们的服务器,并接收有关服务器已识别内容的信息。有时服务器什么也没识别(不是很有趣的情况),有时一件事,有时不止一件事。

所以我必须在列表(RecyclerView)中显示的数据是一张照片(加上时间戳),然后是服务器识别出的一个或多个“事物”。

我的数据结构如下:

List<List<Thing>> masterList;

所以我有一个RecyclerView,其中包含2种可能的项目-单件物品-在其中显示图片,时间和事物信息,或者多件物品在其中显示图片,时间戳和事物列表

这是更高级别的适配器

public class ResultsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<List<Thing>> resultList;
private Context context;

public ResultsAdapter(List<List<Thing>> resultList) {
    this.resultList = resultList;
}

@Override
@NonNull
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    context = parent.getContext();

    RecyclerView.ViewHolder holder;
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    switch (viewType) {
        case 0: // regular single thing card
        {
            View itemView = inflater.inflate(R.layout.thing_item, parent, false);

            holder =  new ResultsHolder(itemView, listener);
            break;
        }
        default: // multi thing card
        {
            View itemView = inflater.inflate(R.layout.compound_item, parent, false);

            holder =  new MultiThingResultsHolder(itemView, listener);
            break;
        }
    }

    return holder;
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
    Resources res = context.getResources();

    switch (viewHolder.getItemViewType()) {
        case 0: // regular single thing card
        {
            ResultsHolder holder = (ResultsHolder) viewHolder;
            holder.time.setText(resultList.get(position).get(0).getTime());

            if (resultList.get(position).get(0).getImage() != null) {
                File thumbnailFile = new File(context.getFilesDir(), resultList.get(position).get(0).getImage());
                holder.thumbnail.setImageURI(Uri.fromFile(thumbnailFile));
            }

        holder.amount.setText(res.getString(R.string.format_blahs, resultList.get(position).get(0).getAmount()));
        .
        .
        .
        .
            break;
        }
        case 2: // multi thing card
        {
            MultiResultsHolder holder = (MultiResultsHolder) viewHolder;
            holder.time.setText(resultList.get(position).get(0).getTime());
            if (resultList.get(position).get(0).getImage() != null) {
                File thumbnailFile = new File(context.getFilesDir(), resultList.get(position).get(0).getImage());
                holder.thumbnail.setImageURI(Uri.fromFile(thumbnailFile));
            }

            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
            holder.list.setLayoutManager(layoutManager);

            List<Thing> subThingList =  resultList.get(position);

            MultiResultsAdapter adapter = new MultiResultsAdapter(subThingList, subListener, position);
            holder.list.setAdapter(adapter);


            break;
        }
    }
}

@Override
public int getItemViewType(int position) {
    if (resultList.get(position).size() == 1) {
        // this is a simple item
        return 0;
    }
    // if we got here it's a multithing item
    return 1;
}


@Override
public int getItemCount() {
    return resultList.size();
}

public class ResultsHolder extends RecyclerView.ViewHolder  {
    private ImageView deleteX;
    public TextView time;
    private ImageView thumbnail;
    private TextView amount;
    .
    .
    .
    .


    private ResultsHolder(View view) {
        super(view);

        deleteX = view.findViewById(R.id.delete_button);
        deleteX.setOnClickListener(this);
        time = view.findViewById(R.id.tv_time);
        thumbnail = view.findViewById(R.id.thumbnail);
        amount = view.findViewById(R.id.tv_amount);
        .
        .
        .
        .
    }

}

private class MultiResultsHolder extends RecyclerView.ViewHolder {
    private ImageView thumbnail;
    public TextView time;
    public RecyclerView list;

    private MultiResultsHolder(View view) {
        super(view);

        time = view.findViewById(R.id.tv_time);
        list = view.findViewById(R.id.list); // <-- the inner Recycler
        thumbnail = view.findViewById(R.id.thumbnail);
    }

}

}

所以我有一个内部适配器,它可以在简单的List<Thing>

上工作
public class MultiResultsAdapter extends RecyclerView.Adapter<MultiResultsAdapter.MultiResultsHolder> {

    private List<Thing> thingList;
    private Context context;

    public MultiResultsAdapter(List<Thing> thingList) {
        this.thingList = thingList;
    }


    @NonNull
    @Override
    public MultiResultsHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
        context = parent.getContext();

        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_sub_item, parent, false);

        return new MultiResultsHolder(itemView);

    }

    @Override
    public void onBindViewHolder(@NonNull MultiResultsHolder holder, int position) {
        Resources res = context.getResources();

        holder.amount.setText(res.getString(R.string.format_blah, thingList.get(position).getAmount()));
                     .
        .
        .
        .

    }

    @Override
    public int getItemCount() {
        return thingList.size();
    }

    public class MultiResultsHolder extends RecyclerView.ViewHolder {
        private ImageView deleteX;
        private TextView amount;
        private TextView fatAmount;
        .    
        .    
        .    
        .    
        private MultiResultsHolder(View view) {
            super(view);
            deleteX = view.findViewById(R.id.delete_button);
            deleteX.setOnClickListener(this);
            amount = view.findViewById(R.id.tv_amount);
            .
            .
            .
        }

    }

}

所以-运行时,单件物品显示得很好。 “内部”代码显示在顶部,该项目的顶部(是一张图片和一个时间戳,并且为列表的其余部分留出了足够的大小(但是其中有很多项目),但其余部分为空白。正在调用第二个适配器,我可以看到onBindViewHolder正在为所有子项插入正确的值,但是它们没有显示出来!

只有一个很大的项目,大部分都是空白。

前后的单个项目都很好,一般的滚动都很好。

我看到一个SO答案,建议我对内部RecyclerView使用CustomLinearLayoutManager,例如here。它没有帮助,但是我看到了一个有趣的异常-在尝试测量项目的高度时,对recycler.getViewForPosition(0)的调用给出了一个超出范围的异常,因为某种程度上RecycleView.Recycler不知道其中有任何项目我认为这可能是一个线索,但我不知道如何使用它来提供帮助

那里有什么主意吗?

1 个答案:

答案 0 :(得分:0)

哇-另一个笨拙的-原来我没有将复合项目的“线性”布局设置为“方向:垂直”,这就是让我搞砸的-很好。这可以解决