向下滚动时 RecyclerView 项目之间的间隙较大

Posted

技术标签:

【中文标题】向下滚动时 RecyclerView 项目之间的间隙较大【英文标题】:Large gap forms between RecyclerView items when scrolling down 【发布时间】:2016-06-19 11:03:39 【问题描述】:

我正在制作一个待办事项列表应用程序,在测试它时,由于某种原因,每当我尝试向下滚动时,项目之间就会形成巨大的差距。每当我拖放项目时总会发生这种情况,但我的 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_
android:layout_
tools:context=".MainActivity"
android:orientation="vertical"
android:weightSum="1">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_
    android:layout_
    android:background="@drawable/rounded_corners" />

<FrameLayout
    android:layout_
    android:layout_>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerList"
        android:layout_
        android:layout_ />

    <RelativeLayout
        android:layout_
        android:layout_>

        <com.melnykov.fab.FloatingActionButton
            android:id="@+id/fab_add"
            android:layout_
            android:layout_
            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_
android:layout_>

<LinearLayout
    android:id="@+id/main"
    android:layout_
    android:layout_>

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

非常感谢任何可以帮助我的人。我一边打字一边拉头发。

编辑:我已经确认问题不是我的 ItemTouchHelper 类。 (尝试在不调用它的情况下运行,问题仍然存在。) 此外,似乎当显示一个对话框并调出键盘时,后台的 RecyclerView 会自行解决问题。删除对话框后,问题再次出现(即滚动会在项目之间放置大量空间)

【问题讨论】:

这可能与您的代码无关。这是关于你的布局。在此处显示您使用的布局。 @DougStevenson 我非常怀疑这会是我的布局,但在这个问题发生之前,我根本没有碰它们。但是,我仍然会感谢您提供的任何见解。 也许这就是原因***.com/questions/35728179/… @Luksprog OMG 你救了我的命谢谢谢谢 在custom.XML文件的相对布局高度中移除Match_parent。 【参考方案1】:

Luksprog 对 Gabriele Mariotti 的回答有效。

根据doc

在 2.3.0 版中,LayoutManager API 有了一个令人兴奋的新功能: 自动测量! 这允许 RecyclerView 根据其内容的大小调整自身大小。 >这意味着以前不可用的场景,例如将 WRAP_CONTENT >用于 RecyclerView 的维度,现在可以实现。 您会发现所有内置的 LayoutManagers 现在都支持自动测量。

由于此更改,请务必仔细检查项目视图的布局参数以前忽略的布局参数(例如 MATCH_PARENT滚动方向)现在将得到完全尊重

在你的项目布局中你必须改变:

android:layout_

android:layout_ 

【讨论】:

正如@mohit 所说,我们还需要将 item_layout 的父布局设置为:xml android:layout_height="wrap_content" 否则将无法正常工作【参考方案2】:

将 Recycler 视图 ma​​tch_parent 更改为 wrap_content

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_
    android:layout_/>

项目布局xml也发生变化

将父布局高度 ma​​tch_parent 设置为 wrap_content

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_
        android:layout_>

        <TextView
            android:id="@+id/textView"
            android:layout_
            android:layout_
        />

【讨论】:

【参考方案3】:

这发生在我身上很多次了!

您需要做的就是...将行文件的 layout_height 设置为 wrap_content 并解决您的问题..

android:layout_height="wrap_content"

编码愉快!

【讨论】:

【参考方案4】:

这是因为您在垂直方向的列表视图/回收器视图中的行项目的根视图的高度使用 ma​​tch_parent。当您使用该项目时,该项目将完全扩展到其父级。 当 recyclerview 是垂直 方向时,使用 wrap_content 作为高度,而当它是 水平 方向时,使用宽度。

【讨论】:

【参考方案5】:

避免使用这样的容器在项目布局中查看视图:

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

<data/>

<android.support.constraint.ConstraintLayout
        android:layout_
        android:layout_>

<TextView
        android:id="@+id/text"
        android:layout_
        android:layout_
        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_
        android:layout_
        android:minHeight="?android:listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</layout>

[注意:以上代码附有数据绑定,如果不使用数据绑定,请不要使用&lt;layout&gt; & &lt;data&gt;标签]

除此之外,如果您必须使用任何视图组容器,请查看容器中的高度和宽度属性,并尝试将它们从 match_parent 更改为 wrap_content。那应该可以解决问题。为了提高透明度,可以尝试提供背景颜色并通过它来识别实际问题。

【讨论】:

【参考方案6】:

仅作记录:因为在我的例子中,我们必须实现一些具有重叠 RecyclerView 和模糊效果工具栏的“超级用户界面”,所以我必须在 RecyclerView-xml 中删除 clipToPadding="false"

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

paddingToppaddingBottom 工作,但我们用一些 GapViews(空视图,paddingTop 和 paddingBottom 的高度)替换它

【讨论】:

【参考方案7】:

如果有人在使用 | recyclerViewObject.setHasFixedSize(true);

尝试删除它,在我的情况下它是导致问题的原因。

【讨论】:

【参考方案8】:

你可以尝试设置你的 Viewgroup 持有 recyclerview 来包装内容

【讨论】:

如果这不起作用,那么你的 recyclerview 布局文件 android:layout_【参考方案9】:

我有这个问题,我只是使用

android:layout_

每个项目的父级。

【讨论】:

以上是关于向下滚动时 RecyclerView 项目之间的间隙较大的主要内容,如果未能解决你的问题,请参考以下文章

在键盘打开时将项目添加到 RecyclerView 时向下滚动

滚动时如何为 recyclerview 项目设置动画?

RecyclerView更新时如何自动向下滚动

滚动时扩展项目之间的 RecyclerView 空间

在 RecyclerView 中滚动时不可见的项目变得可见

NestedScrollview 内的 RecyclerView 滚动不顺畅