2017-03-18 49 views
0

我有以下代碼爲例。回收站的奇怪行爲

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

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中

<?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

<?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> 

它的工作這麼好,是正確的。當我滾動瀏覽列表時,我會在日誌中逐個接收來自Adapter的消息:「onBindViewHolder:」+位置。但接下來我的問題。當我嘗試在RecyclerView之上添加一些視圖時,如下面的代碼所示。適配器同時顯示方法onBindViewHolder的所有調用。在下一個代碼中將RecyclerView包裝在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.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> 

回答

2

RecyclerView是一個ListView。它只會顯示您當前可以看到的項目,在您滾動時重新使用部件。

現在,您將RecyclerView包裝在LinearLayout內的NestedScrollView內,會發生什麼情況?

A NestedScrollView需要知道大小LinearLayout來處理滾動。
LinearLayout如何知道它應該是多長時間,而不知道RecyclerViews的總長度? 它沒有。

所以recyclerView得到完全充氣,一次所有的意見,都在一條長長的線。沒有回收,沒有重複使用。這是你遇到的現象。
現在LinearLayout能夠正確說出NestedScrollView它的高度(TextView的總高度和的RecyclerView的所有項目)和NestedScrollView可以處理滾動。


這就是爲什麼嵌套的滾動是總是一個壞主意。如果可能,請嘗試將TextView作爲項目轉換爲的RecyclerView並擺脫包裝NestedScrollview
例如如下所示:Is there an addHeaderView equivalent for RecyclerView?

另一種選擇是從滾動視圖中刪除recyclerview並將其放在下面。不過,標題不會滾動。

+0

什麼解釋。 – MadScientist

+0

這真的很累 – Mike

+0

我按照所說的添加了標題,一切正常,但我的最後一項並不完全適合RecyclerVIew。最後一項在標題的高度上裁剪, – Mike

0

除非你有一個很好的理由在您的層次結構中的NestedScrollView,你可以實現在上面一個TextView下面只此佈局代碼RecyclerView :

<?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>