看代碼學知識之(2) ListView無數據時顯示其他View
今天看的一塊布局是這樣的:
<!-- The frame layout is here since we will be showing either the empty view or the list view. --> <FrameLayout android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" > <!-- Here is the list. Since we are using a ListActivity, we have to call it "@android:id/list" so ListActivity will find it --> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:drawSelectorOnTop="false" /> <!-- Here is the view to show if the list is emtpy --> <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent" android:text="No items." android:textAppearance="?android:attr/textAppearanceMedium" /> </FrameLayout>
這部分布局實際顯示的效果卻只有一個ListView,里面是數組的數據。
於是,我很好奇這個TextView去了哪里,既然放在同一個FrameLayout中,它難道不是在上層擋着?
顯然,唯一沒見過的就是這個TextView的id的屬性設置:
android:id="@android:id/empty"
搜索了一下,原來這個屬性值的作用就是,當ListView關聯的Adapter中數據為空時,就顯示這個TextView。
而這個ListView中有數據顯示時,這個TextView是不可見的。
使用場景1
上面的布局是一個ListFragment所用的布局中的一塊,同理,當Activity繼承ListActivity時,可以直接實現。
即,在布局中直接用id表達,不需要附加代碼:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- Here is the view to show if the list is emtpy --> <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="No items." /> </FrameLayout>
package com.example.emptylist; import android.os.Bundle; import android.app.Activity; import android.app.ListActivity; import android.view.Menu; import android.widget.ArrayAdapter; import android.widget.ListView; public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, generateStrings()); setListAdapter(adapter); } private String[] generateStrings() { String[] strings = new String[0]; for (int i = 0; i < strings.length; ++i) { strings[i] = "String " + i; } return strings; } }
這樣當數組長度為0時,將自動顯示TextView中的內容。而有數據時,顯示ListView。
使用場景2
如果選擇不繼承ListActivity,則上面例子中的TextView,即便id被設置為android:id="@android:id/empty",也不是只有ListView為空時才顯示。
事實上,因為在FrameLayout中,所以這個TextView會一直顯示在ListView層之上。
當ListView無數據時只顯示TextView;但是ListView有數據時,仍然顯示這個提示“No items”的TextView(which is obviously wrong!)。
此時這個TextView的顯示與否和ListView的數據沒有什么關系了。
對於不繼承ListActivity的情況,要實現上面的效果應該如何呢?
首先,ListView和TextView的id可以任意設置。
然后,只需要調用在代碼中調用setEmptyView(View emptyView)設置ListView為空時顯示這個TextView即可。
布局和代碼如下:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/myList" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- Here is the view to show if the list is emtpy --> <TextView android:id="@+id/myText" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="No items." /> </FrameLayout>
Activity:
package com.example.emptylist; import android.os.Bundle; import android.app.Activity; import android.app.ListActivity; import android.view.Menu; import android.widget.ArrayAdapter; import android.widget.ListView; public class MainActivity extends Activity { private ListView mListView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.myList); mListView.setEmptyView(findViewById(R.id.myText)); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, generateStrings()); mListView.setAdapter(adapter); } private String[] generateStrings() { String[] strings = new String[100]; for (int i = 0; i < strings.length; ++i) { strings[i] = "String " + i; } return strings; } }
擴展:
因為setEmptyView(View emptyView)這個方法是屬於AdapterView這個類的,所以除了ListView之外,其他的子類,如GridView,Spinner等,應該也可以用這個方法來設置Adapter數據為空時顯示另一個View。