Вложенные RecyclerViews, внутренний переработчик не отображается

У меня есть приложение, которое отправляет изображения на наш сервер и получает информацию о том, что идентифицировал сервер. Иногда сервер ничего не идентифицирует (неинтересный случай), иногда одно, иногда более одного.

Таким образом, данные, которые я должен показать в списке (RecyclerView), представляют собой фотографию (плюс отметку времени), а затем одну или несколько «вещей», идентифицированных сервером.

Моя структура данных выглядит так:

List<List<Thing>> masterList;

Итак, у меня есть RecyclerView с двумя возможными элементами: либо элемент с одной вещью, где я показываю изображение, время и информацию о вещи, либо элемент с несколькими вещами, где я показываю изображение, отметку времени и список вещей.

Вот адаптер более высокого уровня

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);
            .
            .
            .
        }

    }

}

Итак, при запуске элементы Single-thing отображаются просто отлично. Элементы Multi-thing отображаются с верхней частью (которая представляет собой изображение и отметку времени и достаточный размер, отведенный для остальной части списка (сколько бы элементов в нем ни было), но остальная часть пуста. Код для внутреннего вызывается второй адаптер, и я вижу, что onBindViewHolder вставляет правильные значения для всех подэлементов, но они не отображаются!

Там просто большой элемент с пустым пространством.

Отдельные элементы до и после просто прекрасны, общая прокрутка в порядке.

Я видел ответ SO, в котором предлагалось использовать CustomLinearLayoutManager для внутреннего RecyclerView, например, здесь. Это не помогло, но я увидел интересное исключение — при попытке измерить высоту элементов вызов recycler.getViewForPosition(0) выдает исключение за пределами границ, потому что каким-то образом RecycleView.Recycler не знает, что в списке есть какие-либо элементы. думал, что это может быть подсказкой, но я не знаю, как ее использовать, чтобы помочь

Есть идеи?

попробуй посмотреть на этот github.com/vivchar/RendererRecyclerViewAdapter/wiki/…

Vitaly 10.04.2019 11:31

Спасибо, Виталий, это была моя глупая ошибка.

Kibi 10.04.2019 11:49
0
2
579
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вау — еще одна дурь — оказалось, что я не сделал линейный макет для своего составного элемента «ориентация: вертикаль» — и это то, что меня напортачило — ну. это исправляет это

Другие вопросы по теме