向下滚动时 RecyclerView 项目之间形成大间隙
Large gap forms between RecyclerView items when scrolling down
我正在制作一个待办事项列表应用程序,在测试它时,出于某种原因,每当我尝试向下滚动时,项目之间就会形成巨大的差距。每当我拖放项目时,它总是会发生,但我没有看到我的 ItemTouchHelper 适配器和回调 class 有任何错误。如果你能帮助我,那就太棒了。
之前:
之后:
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 class。 (试过 运行 没有被调用,问题仍然存在。)
此外,似乎在显示对话框并调出键盘时,后台的 RecyclerView 自行解决了问题。删除对话框后,问题重复出现(即滚动在项目之间放置大量 space)
Luksprog 对 Gabriele Mariotti 的回答有效。
根据doc
With the release 2.3.0 there is an exciting new feature to the LayoutManager API:
auto-measurement!
This allows a RecyclerView to size itself based on the size of its contents. >This means that previously unavailable scenarios, such as using WRAP_CONTENT >for a dimension of the RecyclerView, are now possible.
You’ll find all built in LayoutManagers now support auto-measurement.
由于此更改,确保仔细检查项目视图的布局参数:之前忽略的布局参数(例如MATCH_PARENT 在滚动方向)现在将 完全尊重。
在您的项目布局中,您必须更改:
android:layout_height="match_parent"
与
android:layout_height="wrap_content"
回收站视图 match_parent 更改为 wrap_content:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
项目布局也有变化 xml
将父布局高度match_parent改为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"
/>
这是因为您在垂直方向 listview/recyclerview 中使用 match_parent 行项目根视图的高度。当您使用该项目时,该项目将完全扩展到其父级。
当 recyclerview 是 垂直 方向时使用 wrap_content 高度,当它是 水平 时使用宽度] 导向。
我有这个问题,我只是使用
android:layout_height="wrap_content"
对于每个项目的父项。
避免使用这样的容器在项目布局中使用视图:
<?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
。那应该可以解决问题。为了更加透明,可以尝试提供背景颜色并通过它来识别实际问题。
仅作记录:因为在我的例子中,我们必须实现一些 "superfancy UI" 与重叠的 RecyclerView 和模糊效果工具栏,我不得不在 RecyclerView
中摆脱 clipToPadding="false"
- 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)
我遇到过很多次!
您需要做的就是...制作 layout_height 行文件 wrap_content,您的问题就解决了..
android:layout_height="wrap_content"
编码愉快!
如果有人正在使用 | recyclerViewObject.setHasFixedSize(真);
尝试删除它,它导致了我的问题。
您可以尝试将持有 recyclerview 的 Viewgroup 设置为包装内容
我正在制作一个待办事项列表应用程序,在测试它时,出于某种原因,每当我尝试向下滚动时,项目之间就会形成巨大的差距。每当我拖放项目时,它总是会发生,但我没有看到我的 ItemTouchHelper 适配器和回调 class 有任何错误。如果你能帮助我,那就太棒了。
之前:
之后:
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 class。 (试过 运行 没有被调用,问题仍然存在。) 此外,似乎在显示对话框并调出键盘时,后台的 RecyclerView 自行解决了问题。删除对话框后,问题重复出现(即滚动在项目之间放置大量 space)
Luksprog 对 Gabriele Mariotti 的回答有效。
根据doc
With the release 2.3.0 there is an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. >This means that previously unavailable scenarios, such as using WRAP_CONTENT >for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
由于此更改,确保仔细检查项目视图的布局参数:之前忽略的布局参数(例如MATCH_PARENT 在滚动方向)现在将 完全尊重。
在您的项目布局中,您必须更改:
android:layout_height="match_parent"
与
android:layout_height="wrap_content"
回收站视图 match_parent 更改为 wrap_content:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
项目布局也有变化 xml
将父布局高度match_parent改为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"
/>
这是因为您在垂直方向 listview/recyclerview 中使用 match_parent 行项目根视图的高度。当您使用该项目时,该项目将完全扩展到其父级。 当 recyclerview 是 垂直 方向时使用 wrap_content 高度,当它是 水平 时使用宽度] 导向。
我有这个问题,我只是使用
android:layout_height="wrap_content"
对于每个项目的父项。
避免使用这样的容器在项目布局中使用视图:
<?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
。那应该可以解决问题。为了更加透明,可以尝试提供背景颜色并通过它来识别实际问题。
仅作记录:因为在我的例子中,我们必须实现一些 "superfancy UI" 与重叠的 RecyclerView 和模糊效果工具栏,我不得不在 RecyclerView
中摆脱 clipToPadding="false"
- 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)
我遇到过很多次!
您需要做的就是...制作 layout_height 行文件 wrap_content,您的问题就解决了..
android:layout_height="wrap_content"
编码愉快!
如果有人正在使用 | recyclerViewObject.setHasFixedSize(真);
尝试删除它,它导致了我的问题。
您可以尝试将持有 recyclerview 的 Viewgroup 设置为包装内容