ListView建议和技巧#1: 处理空视图

注: 这是“ListView建议和技巧 ”系列文章中的第一篇。在Android上开发,经常需要显示大的数据集合(通信录、歌曲等等)。大多情况下,这些数据都是类似的并可以通过ListView控件进行统一显示。ListView在Android界面中使用时大多是原本的样子。但是,基于ListView的应用可以通过一些简单的技巧进行定制、优化或者修饰。该系列博客就是介绍一些可以用于加强和改进应用的一些技巧。

 

简介

在应用中显示一个数据集时,推荐处理如下一些情形:

  • 正常情况:底层数据集由一个或者多个条目组成
  • 数据为空的情况:和上述定义相反。底层数据集为空时就是数据为空的情况

从用户的角度看,两种情形有不同的界面很重要。确实,它可以帮助用户区分两种“数据”状态。在开发应用时不要忘了这点。

数据为空时的视图(空视图)

ListView或者更广义地说是AdapterView(Gallery、GridView等等)可以很简单地处理空视图情形。AdapterView公开了一个称作setEmptyView(View)的方法来讲一个View绑定到自身。一旦设定了数据为空时的视图,AdapterView就会根据地层Adapter的状态(是否为空)来隐藏或显示该视图。

AdapterView和空视图在可见性方面是互斥的,如果空视图可见(View.VISIBLE),AdapterView就将其视图的可见性设置成View.GONE,相反情形也类似。AdapterView根据如下条件判断其是否为空:

  • 底层Adpater时null
  • 调用底层Adapter的isEmpty()返回真

ListActivity

Android框架还提供了一个在界面中使用ListView的很方便的方法。Android提供了一个专用的Acitivity:ListActivity。在通过setContentView方法设定一个新的布局时,ListActivity就自动查找一个标识符是android.R.id.list的ListView并开始管理它。它还会查找一个标识符是android.R.id.empty的视图。一旦存在这样的视图,就会被直接设置成之前ListView的数据为空时的视图。这样,在ListActivity中处理数据为空时的视图就很简单,仅仅需要在布局中加入一个android:id属性是@android:id/empty的视图。

 

示例

为了展示下如何配置处理数据为空时的视图的代码,我制作了一个简单的应用。该应用仅仅显示带有一个ListView和两个Button的界面。两个按钮帮助你清空或者填充ListView的数据。可以从如下链接获取到应用的完整代码:

ListViewTipsAndTricks archive

正如之前看到的,我们会使用ListActivity让代码尽可能简单清晰。所需要做的唯一一件事情就是在布局中包括一个标识符是@android:id/empty的视图。ListActivity会处理所有的事情!如下的布局有三部分组成:

  • 标识符是@android:id/list的ListView
  • 标识符是@android:id/empty的一个数据为空时的视图
  • 在屏幕下方的一些控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_;fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <FrameLayout
        android:layout_;fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <ListView
            android:id="@android:id/list"
            android:layout_;fill_parent"
            android:layout_height="fill_parent" />
        <ViewStub
            android:id="@android:id/empty"
            android:layout_;wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout="@layout/empty" />
    </FrameLayout>
    <LinearLayout
        style="@android:style/ButtonBar"
        android:layout_;fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:layout_;0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/set_empty"
            android:onClick="onSetEmpty" />
        <Button
            android:layout_;0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/set_data"
            android:onClick="onSetData" />
    </LinearLayout>
</LinearLayout>

提示: 你们可能注意到了,我使用了一个ViewStub作为空视图。ViewStub使得你可以在需要的时候(这就是即时填充)填充视图。在之前的例子中,@layout/empty布局仅仅在ViewStub的可视性变成View.VISIBLE后被填充。一旦@layout/empty视图被填充,它就会在全局布局中替换ViewStub。如果你不熟悉该类,建议查看下ViewStub文档。

这样在一个简单的ListActivity中就可以使用该布局了:

package com.cyrilmottier.android.listviewtipsandtricks;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;


public class EmptyListActivity extends ListActivity {
    private static final String EMPTY[] = {};
    private static final String CHEESES[] = {
            "Abbaye de Belloc",
            // ...
            "Zanetti Parmigiano Reggiano"
    };
    private CheeseAdapter mAdapter;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.empty_list);
        mAdapter = new CheeseAdapter(CHEESES);
        setListAdapter(mAdapter);
    }


    public void onSetEmpty(View v) {
        mAdapter.changeData(EMPTY);
    }


    public void onSetData(View v) {
        mAdapter.changeData(CHEESES);
    }


    private class CheeseAdapter extends BaseAdapter {
        private String[] mData;


        public CheeseAdapter(String[] data) {
            mData = data;
        }


        public void changeData(String[] data) {
            mData = data;
            notifyDataSetChanged();
        }


        @Override
        public int getCount() {
            return mData.length;
        }


        @Override
        public String getItem(int position) {
            return mData[position];
        }


        @Override
        public long getItemId(int position) {
            return position;
        }


        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.text_item, parent, false);
            }
            ((TextView) convertView).setText(getItem(position));
            return convertView;
        }
    }
}

       就是这些了,简单吧?处理ListView数据为空时的情形可以很简单。在开发Android应用时,不要吝惜添加空视图。在使用解释文字的同时加入别出心裁的Drawable会比什么都不显示好…剩下的就靠你的想象力了!

 

原文链接:http://android.cyrilmottier.com/?p=422

你可能感兴趣的:(ListView,职场,休闲,空视图)