Большой разрыв образуется между элементами RecyclerView при прокрутке вниз

Я делаю приложение со списком дел, и, по какой-то причине, во время его тестирования возникает огромный разрыв между элементами, когда я пытаюсь прокрутить вниз. Это всегда происходит всякий раз, когда я перетаскиваю элементы, но я не вижу никаких ошибок с моим адаптером ItemTouchHelper и классом обратного вызова. Было бы здорово, если бы вы могли мне помочь.

До:До

После:После

RecyclerAdapter.java

public class RecyclerAdapter extends                                                                                                                                 

RecyclerView.Adapter<RecyclerAdapter.RecyclerVH> implements ItemTouchHelperAdapter{
private LayoutInflater layoutInflater;
ArrayList<Info> data;
Context context;

public RecyclerAdapter(Context context) {
    layoutInflater = LayoutInflater.from(context);
    this.context = context;
}

public void setData(ArrayList<Info> data) {
    this.data = data;
    notifyDataSetChanged();
}

@Override
public RecyclerVH onCreateViewHolder(ViewGroup viewGroup, int position) {
    View view = layoutInflater.inflate(R.layout.custom_row, viewGroup, false);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("R.A onClick Owen", "onClick method triggered");
        }
    });
    RecyclerVH recyclerVH = new RecyclerVH(view);
    return recyclerVH;
}

@Override
public void onBindViewHolder(RecyclerVH recyclerVH, int position) {
    Log.d("RecyclerView", "onBindVH called: " + position);

    final Info currentObject = data.get(position);
    // Current Info object retrieved for current RecyclerView item - USED FOR DELETE
    recyclerVH.listTitle.setText(currentObject.title);
    recyclerVH.listContent.setText(currentObject.content);

    /*recyclerVH.listTitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Open new Activity containing note content
            Toast.makeText(this, "Opening: " + currentObject.title, Toast.LENGTH_LONG).show();
        }
    });*/
}

public void deleteItem(int position) {
    DBInfo dbInfo = new DBInfo(context);
    dbInfo.deleteNote(data.get(position));
    // Deletes RV item/position's Info object

    data.remove(position);
    // Removes Info object at specified position

    notifyItemRemoved(position);
    // Notifies the RV that item has been removed
}


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

// This is where the Swipe and Drag-And-Drog methods come into place
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
    // Swapping positions
    // ATTEMPT TO UNDERSTAND WHAT IS GOING ON HERE
    Collections.swap(data, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
    return true;
}

@Override
public void onItemDismiss(int position) {
    // Deleting item from RV and DB
    deleteItem(position);
}

class RecyclerVH extends RecyclerView.ViewHolder implements View.OnClickListener{
    // OnClickListener is implemented here
    // Can also be added at onBindViewHolder above
    TextView listTitle, listContent;

    public RecyclerVH(View itemView) {
        super(itemView);

        listTitle = (TextView) itemView.findViewById(R.id.title);
        listContent = (TextView) itemView.findViewById(R.id.content);

        listTitle.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Toast.makeText(context, "Opening: Note" + getLayoutPosition(), Toast.LENGTH_SHORT).show();
        // PS NEVER ADD listTitle VARIABLE AS PUBLIC VARIABLE ABOVE WHICH IS GIVEN VALUE AT ONBINDVH
        // THIS IS BECAUSE THE VALUE WILL CHANGE IF ITEM IS ADDED OR DELETED
    }
}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:weightSum="1">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/rounded_corners" />

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <com.melnykov.fab.FloatingActionButton
            android:id="@+id/fab_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:layout_marginBottom="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginEnd="16dp"
            android:gravity="bottom|end"
            android:onClick="addNote"
            android:src="@drawable/fab_ic_add"
            fab:fab_colorNormal="@color/colorPrimary"
            fab:fab_colorPressed="@color/colorPrimaryDark"
            fab:fab_colorRipple="@color/colorPrimaryDark" />
    </RelativeLayout>
</FrameLayout>
</LinearLayout>

custom_row.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:id="@+id/main"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:padding="8dp"
        android:text="@string/test"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/main"
    android:paddingLeft="8dp">
    <TextView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/test"
        android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>

Большое спасибо тому, кто может мне помочь. Я вытягиваю волосы, когда печатаю.

РЕДАКТИРОВАТЬ: я подтвердил, что это не мой класс ItemTouchHelper, что проблема. (Пробная работа без вызова, проблема все еще возникает.) Кроме того, кажется, что когда отображается диалоговое окно и вызывается клавиатура, RecyclerView в фоновом режиме решает проблему самостоятельно. После удаления диалогового окна проблема повторяется (т. Е. Прокрутка помещает большое пространство между элементами)

8 ответов

Решение

Ответ Luksprog на ответ Габриэле Мариотти работает.

Согласно документу

В выпуске 2.3.0 появилась новая замечательная функция API LayoutManager: автоматическое измерение! Это позволяет RecyclerView изменять размер в зависимости от размера его содержимого. > Это означает, что ранее недоступные сценарии, такие как использование WRAP_CONTENT > для измерения RecyclerView, теперь возможны. Вы найдете, что все встроенные в LayoutManager теперь поддерживают автоматическое измерение.

Из-за этого изменения дважды проверьте параметры макета ваших видов элементов: ранее проигнорированные параметры макета (такие как MATCH_PARENT в направлении прокрутки) теперь будут полностью соблюдаться.

В вашем макете вы должны изменить:

android:layout_height="match_parent"

с

android:layout_height="wrap_content" 

Изменить в представлении Recycler match_parent на wrap_content:

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

Также изменить в макете элемента XML

Сделать высоту родительского макета совпадающей с wrap_content

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
        />

Это случалось со мной много раз!

Все, что вам нужно сделать, это... сделать layout_height файла строки wrap_content и ваша проблема решена..

android:layout_height="wrap_content"

Удачного кодирования!

Это потому, что вы используете match_parent по высоте от корневого представления элемента строки в вашем вертикально ориентированном представлении listview/recyclerview. Когда вы используете это, элемент полностью расширяется по отношению к своему родителю. Используйте wrap_content для высоты, когда окно рециркуляции ориентировано вертикально, и для ширины, когда оно ориентировано горизонтально.

Просто для справки: поскольку в моем случае нам пришлось реализовать какой-то "сверхъестественный пользовательский интерфейс" с перекрывающимся RecyclerView и панелью инструментов эффекта размытия, мне пришлось избавиться от clipToPadding="false" в RecyclerView-xml.

<android.support.v7.widget.RecyclerView
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:paddingTop="@dimen/height_toolbar"
  android:paddingBottom="@dimen/height_bottom_bar_container"
  //android:clipToPadding="false" <-- remove this flag!
  android:scrollbars="vertical"
/>

paddingTopа также paddingBottom работал, но мы заменили его на некоторые GapViews(пустые представления, с высотой paddingTop и paddingBottom)

Если кто-то использует | recyclerViewObject.setHasFixedSize(истина);

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

Старайтесь не брать представление в макете элемента с контейнером, подобным этому:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data/>

<android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

<TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</android.support.constraint.ConstraintLayout>
</layout>

как в этом случае match_parent сделает свое дело и проблема все равно останется! Скорее возьмите это так:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data/>

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</layout>

[Примечание: выше код имеет привязку данных, не используйте <layout> & <data> теги, если не используется привязка данных]

Кроме этого, если вам необходимо использовать какие-либо контейнеры группы представлений, посмотрите атрибуты высоты и ширины в контейнере и попробуйте изменить их с match_parent в wrap_content, Это должно решить проблему. Для большей прозрачности можно попытаться задать фоновые цвета и посмотреть сквозь них, чтобы определить актуальную проблему.

Вы можете попытаться настроить вашу Viewgroup, содержащую реселлер, чтобы обернуть содержимое

У меня есть эта проблема, и я просто пользователь

android:layout_height="wrap_content"

для родителя каждого элемента.

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