Как реализовать множественные повторные просмотры в одном макете?

Tom11 спросил: 12 мая 2018 в 04:00 в: android

Я хочу создать панель, в которой есть два RecyclerView s (скажем, "MyItems", "AllItems"). Я создал вертикальный LinearLayout, в котором есть TextView как title и RecyclerView. Что-то вроде этого:

 <LinearLayout ... >    <TextView
        android:text="My Items"
        ... />    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_items"
        ... />    <TextView
        android:text="All Items"
        ... />    <android.support.v7.widget.RecyclerView
        android:id="@+id/all_items"
        ... /></LinearLayout>

Однако при таком подходе только recyclerViews прокручиваются независимо, но мне нужно, чтобы весь макет был прокручиваемым (так что сначала он прокручивает первую секцию, затем второй). Я попытался завершить его в ScrollView и NestedScrollView, но ближайший я получил прокрутку без гладкой анимации.

Мой вопрос is, этот подход действителен, и если да, то есть ли способ добавить плавную прокрутку в NestedScrollView? Или я должен реализовать это, используя другой подход, например. создайте ListView, который содержит два элемента с макетом, содержащим TextView и RecyclerView?

ListView

  • Элемент списка 1

    • Заголовок 1
    • RecyclerView 1
  • Элемент списка 2

    • Заголовок 2
    • RecyclerView2
  • Я считаю, что этот подход не очень хорош с точки зрения производительности. Я прав? Мне просто нужно найти для этого наилучшую практику. Спасибо.

    3 ответа

    Есть решение
    Shashwat ответил: 12 мая 2018 в 05:52

    Пожалуйста, не используйте вложенную прокрутку. Это приведет к поражению цели просмотра recycler и сохранит все внутри памяти, так как высота будет установлена ​​как максимум для обоих ресайклеров. Вместо этого выполните следующие два варианта:

    1.Если вы не имеют определенный фон, создайте один RecyclerView с адаптером, похожим на следующий:

    public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{    ArrayList<Integer> data = new ArrayList<>();
        private final int VIEW_TYPE_TEXTVIEW = 0;
        private final int VIEW_TYPE_ITEM_1 = 1;
        private final int VIEW_TYPE_ITEM_2 = 2;
        private final LayoutInflater inflater;
        private final ArrayList<Integer> data;    public MyRecyclerAdapter(Context ctx, ArrayList<Integer> data){
            this.context = ctx;
            this.data = data;
            inflater = LayoutInflater.from(context);
        }    @Override
        public int getItemViewType(int position) {
            return data.get(position);
        }    @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            if(viewType == VIEW_TYPE_TEXTVIEW){
                View view = inflater.inflate(R.layout.simple_textview, parent, false);
                return new TextViewHolder(view);
            }else if(viewType == VIEW_TYPE_ITEM_1){
                View view = inflater.inflate(R.layout.item_top_recycler, parent, false);
                return new Item1Holder(view);
            }else{
                View view = inflater.inflate(R.layout.item_bottom_recycler, parent, false);
                return new Item2Holder(view);
            }
        }    @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            if(holder instanceof TextViewHolder){
                ((TextViewHolder) holder).textView.setText(...);
            }else if(holder instanceof Item1Holder){
                ((Item1Holder) holder).itemTextView.setText(...);
            }else if(holder instanceof Item2Holder){
                ((Item2Holder) holder).itemTextView.setText(...);
            }
        }    @Override
        public int getItemCount() {
            return data.size();
        }    class TextViewHolder extends RecyclerView.ViewHolder {        TextView textView;        public HeaderHolder(View itemView) {
                super(itemView);
                textView = itemView.findViewById(R.id.tv);
            }
        }
        class Item1Holder extends RecyclerView.ViewHolder {        TextView itemTextView;        public HeaderHolder(View itemView) {
                super(itemView);
                itemTextView = itemView.findViewById(R.id.tv);
            }
        }
        class Item2Holder extends RecyclerView.ViewHolder {        TextView itemTextView;        public HeaderHolder(View itemView) {
                super(itemView);
                itemTextView = itemView.findViewById(R.id.tv);
            }
        }
    }
    

    Затем установите адаптер следующим образом:

    ArrayList<Integer> data = new ArrayList<>();
    //Adding first textview
    data.add(0);
    //Adding 10 elements of first RecyclerView
    for(int i = 0; i<10; i++){
        data.add(1);
    }
    //Adding second textview
    data.add(0);
    //Adding 10 elements of second RecyclerView
    for(int i = 0; i<10; i++){
        data.add(2);
    }adapter = new MyRecyclerAdapter(this, data);
    navView.setAdapter(adapter);
    

    Таким образом, вы можете использовать RecyclerView, чтобы также содержать текст. Этот метод даст вам лучшую оптимизацию. Убедитесь, что вы возвращаете соответствующий VIEW_TYPE в getItemViewType () для вашего верхнего recyclerView, ниже RecyclerView и TextViews.

    Второй метод - иметь один RecyclerView, содержащий 4 элемента:

      TextView
    • LinearLayout
    • TextView
    • LinearLayout

    Затем динамически заполняйте эти LinearLayouts элементами. Это гарантирует, что по крайней мере один из Linringayout будет переработан, если его не видно. Даже тогда первый подход будет гораздо лучшим подходом.

    Tom11 ответил: 12 мая 2018 в 05:27
    Спасибо за отличный пример. Однако, не могли бы вы объяснить мне, как onCreateViewHolder знает правильный viewType? Где вы это устанавливаете?
    Shashwat ответил: 12 мая 2018 в 05:48
    Вы можете изменить getItemViewType(). Прямо сейчас он возвращает числа, которые я вставляю, создавая объект адаптера. Если у него есть 0, элемент будет обрабатываться как текстовое изображение, если число равно 1, верхний элемент recyclerview и 2 для более низкого элемента recyclerview.
    Shashwat ответил: 12 мая 2018 в 05:51
    Если бы это сработало для вас, можете ли вы принять мой ответ правильно, пожалуйста?
    Levi Moreira ответил: 12 мая 2018 в 04:18

    Вам следует попробовать решение NestedScrollView, которое, по вашему мнению, было самым близким к тому, что вы хотели:

    NestedScrollView
       TextView
       RecyclerView
       TextView
       RecyclerView
    

    И чтобы иметь гладкую прокрутку, вам нужно установить свойство в своих просмотрах recycler :

     recyclerView.setNestedScrollingEnabled(false);
    

    Таким образом, ваш макет будет прокручивать NestedScrollView, а не RV.

    Kalyan Dechiraju ответил: 12 мая 2018 в 04:21

    Прежде всего, не рекомендуется иметь два вида ресайклеров на одном экране, если для этого нет веской причины. Попробуйте использовать разные разделы с заголовками в одном просмотре ресайклеров.

    Если вы все еще хотите использовать, вставьте макет в NestedScrollView и установите для свойства recoclerView nestedScrollingEnabled значение

    recyclerView.setNestedScrollingEnabled(false);
    

    Совет. Проверьте FastAdapter, который упрощает работу.

    Tom11 ответил: 12 мая 2018 в 04:25
    После этого мне нужно отобразить "мои предметы" и "все предметы". Может быть, будет еще один "раздел". Как это можно сделать с помощью одного recyclerView? Не будет ли поддерживать только один RecyclerView в большей сложности?
    Kalyan Dechiraju ответил: 12 мая 2018 в 04:32
    Ключом для поддержки нескольких разделов является метод onCreateViewHolder(parent: ViewGroup, viewType: Int) адаптера RecyclerView, где вы можете решить, какой вид просмотра он и раздуть представление соответственно.
    Kalyan Dechiraju ответил: 12 мая 2018 в 04:36
    Существует множество библиотек, облегчающих эту работу, чем создание всего самого себя. Проверьте это сообщение (или похожие) для получения более подробной информации, если вы хотите установить с нуля.
    Levi Moreira ответил: 12 мая 2018 в 04:45
    Очень хорошие приложения, такие как facebook, youtube, netflix и даже игровой магазин, используют два или более RV в одном макете (для внешнего вида)
    Kalyan Dechiraju ответил: 12 мая 2018 в 04:47
    Вы имеете в виду горизонтальный список прокрутки внутри вертикального списка прокрутки?