[英]Strange behavior of the RecyclerView
I have the following code for example. 我有以下代码为例。
MainActivity.java MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> names = new ArrayList<>();
names.add("one");
names.add("two");
names.add("three");
names.add("four");
names.add("five");
names.add("six");
names.add("seven");
names.add("eight");
names.add("nine");
names.add("ten");
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(this);
rv.setLayoutManager(llm);
RvAdapter adapter = new RvAdapter(names);
rv.setAdapter(adapter);
}
}
RvAdapter.java RvAdapter.java
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.PersonViewHolder> {
public static final String TAG = RvAdapter.class.getSimpleName();
List<String> persons;
RvAdapter(List<String> persons) {
this.persons = persons;
}
@Override
public RvAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new PersonViewHolder(v);
}
@Override
public void onBindViewHolder(RvAdapter.PersonViewHolder holder, int position) {
holder.name.setText(persons.get(position));
Log.d(TAG, "onBindViewHolder: " + position);
}
@Override
public int getItemCount() {
return persons.size();
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView name;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
name = (TextView) itemView.findViewById(R.id.name);
}
}
}
activity_main.xml activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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="com.example.mrmayhem.myapplication.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
item.xml item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<android.support.v7.widget.CardView
android:id="@+id/cv"
android:layout_width="match_parent"
android:layout_height="200dp">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.CardView>
</LinearLayout>
It works so good and correct. 它是如此的好和正确。 When I scroll through the list I get successive messages from Adapter one by one in Logs: "onBindViewHolder: " + position.
当我滚动列表时,在日志中依次从适配器获得连续的消息:“ onBindViewHolder:” +位置。 But my problem in next.
但是我接下来的问题。 When i try add some View above the
RecyclerView
, as shown in the code below. 当我尝试在
RecyclerView
上方添加一些View时,如下面的代码所示。 Adapter displays all calls of the method onBindViewHolder
simultaneously . 适配器的显示器的方法的所有调用
onBindViewHolder
同时 。 Wrap the RecyclerView
in activity_main.xml by the next code. 通过下一个代码将
RecyclerView
包裹在activity_main.xml中 。
activity_main.xml (with header) activity_main.xml(带标题)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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="com.example.mrmayhem.myapplication.MainActivity">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HEADER" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
RecyclerView is a ListView. RecyclerView是一个ListView。 It will only display the items that you can currently see, reusing parts as you scroll.
它将仅显示您当前可以看到的项目,并在滚动时重复使用零件。
Now you wrap the RecyclerView in a LinearLayout
within a NestedScrollView
, what happens? 现在,将RecyclerView包装在
NestedScrollView
内的LinearLayout
中,会发生什么情况?
A NestedScrollView
needs to know the size of the LinearLayout
to handle the scrolling. NestedScrollView
需要知道LinearLayout
的大小才能处理滚动。
How does the LinearLayout
know how long it should be, without knowing the RecyclerViews total length? LinearLayout
如何在不知道RecyclerViews总长度的情况下知道应该多长? It doesn't. 没有。
So the recyclerView gets completely inflated, all views at once, all in a long line. 因此,recyclerView会完全膨胀,所有视图一次排成一行。 No recycling, no reuse.
不回收,不重复使用。 This is the phenomenon you experience.
这就是您遇到的现象。
Now the LinearLayout
can properly tell the NestedScrollView
it's height (the total height of the TextView and all the items of the RecyclerView) and the NestedScrollView
can handle the scrolling. 现在,
LinearLayout
可以正确告知NestedScrollView
它的高度(TextView和RecyclerView的所有项目的总高度),而NestedScrollView
可以处理滚动。
This is why nested scrolling is always a bad idea. 这就是为什么嵌套滚动始终是一个坏主意的原因。 If possible, try to move your
TextView
as an item into the RecyclerView and get rid of the wrapping NestedScrollview
. 如果可能,请尝试将
TextView
作为一项移至 RecyclerView中,并摆脱包装的NestedScrollview
。
eg as seen here: Is there an addHeaderView equivalent for RecyclerView? 例如,如此处所示: RecyclerView是否具有等效的addHeaderView?
Another option would be to remove the recyclerview from the scroll view and put it below. 另一个选择是从滚动视图中删除recyclerview并将其放在下面。 The header would not scroll then, though.
但是,标题将不会滚动。
Unless you have a good reason to have a NestedScrollView
in your hierarchy, you could achieve a TextView on top with a RecyclerView below with just this layout code: 除非您有充分的理由在您的层次结构中使用
NestedScrollView
,否则可以使用以下布局代码在顶部使用下面的RecyclerView来实现TextView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.mrmayhem.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HEADER" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.