Mono for Android 下的 ListActivity 使用介紹

張志敏的技術專欄發表於2015-03-21

介紹 Mono for Android 平臺下 ListActivity 的使用, 以及如何進行自定義 ListActivity 的 Adapter。

使用 ListActivity 最簡單的方式

ListActivity 是 android 開發中很常用的佈局元件, 通常用於顯示可以滾動的列表項。 以 ArrayAdapter<T> 為例, 最簡單的使用方法如下:

1、 新建一個 Activity , 名稱為 MyListActivity , 並修改其基類為 Android.App.ListActivity, 程式碼如下:

[Activity (Label = "MyListApp", MainLauncher = true)]
public class MyListActivity : ListActivity {

    protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);
    }
}

2、 新增一個字串陣列欄位作為資料來源, 程式碼如下:

// 最簡單的方法, 用陣列作為資料來源
private readonly string[] _countries = new String[] {
    "Afghanistan","Albania","Algeria","American Samoa","Andorra",
    "Angola","Anguilla","Antarctica","Antigua and Barbuda","Argentina",
    "Armenia","Aruba","Australia","Austria","Azerbaijan",
    "Bahrain","Bangladesh","Barbados","Belarus","Belgium",
    "Belize","Benin","Bermuda","Bhutan","Bolivia",
    "Bosnia and Herzegovina","Botswana","Bouvet Island","Brazil",
    "British Indian Ocean Territory"
};

3、 在 OnCreate 方法中設定 ListView 的資料來源, 程式碼如下:

protected override void OnCreate(Bundle bundle) {
    base.OnCreate(bundle);
    // 設定 ListAdapter 為 ArrayAdapter<string>
    this.ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.MyListActivityItemLayout, this._countries);
    this.ListView.TextFilterEnabled = true;
    // 新增一個建大的事件處理函式, 以通知的形式顯示選中項。
    this.ListView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => {
        var toast = Toast.MakeText(this.Application, ((TextView)e.View).Text, ToastLength.Short);
        toast.Show();
    };

}

現在, 完整的 MyListActivity.cs 看起來應該是這樣子的:

[Activity(Label = "ListDemo", MainLauncher = true)]
public class MyListActivity : ListActivity {

    private readonly string[] _countries = new String[] {
        "Afghanistan","Albania","Algeria","American Samoa","Andorra",
        "Angola","Anguilla","Antarctica","Antigua and Barbuda","Argentina",
        "Armenia","Aruba","Australia","Austria","Azerbaijan",
        "Bahrain","Bangladesh","Barbados","Belarus","Belgium",
        "Belize","Benin","Bermuda","Bhutan","Bolivia",
        "Bosnia and Herzegovina","Botswana","Bouvet Island","Brazil",
        "British Indian Ocean Territory"
    };

    protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);

        // Create your application here
        this.ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.MyListActivityItemLayout, this._countries);
        this.ListView.TextFilterEnabled = true;

        this.ListView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => {
            var toast = Toast.MakeText(this.Application, ((TextView)e.View).Text, ToastLength.Short);
            toast.Show();
        };
    }
}

如果現在執行程式, 看到的效果如下:

List Activity

ListActivity的使用就是這麼簡單, 但是這往往不是我們所需要的, 接下來將會對上面的程式碼進行一些重構。

使用 String-Array 作為 ListActivity 資料來源

把要顯示的列表作為 Android 資源是個不錯的注意, 減少對顯示內容的硬編碼, 必要時還可以方便的實現多語言顯示, 在 Assets/values/strings.xml 檔案中新增下面的內容:

<string-array name="CountryArray">
    <item>Afghanistan</item>
    <item>Albania</item>
    <item>Algeria</item>
    <item>American Samoa</item>
    <item>Andorra</item>
    <item>Angola</item>
    <item>Anguilla</item>
    <item>Antarctica</item>
    <item>Antigua and Barbuda</item>
    <item>Argentina</item>
    <item>Armenia</item>
    <item>Aruba</item>
    <item>Australia</item>
    <item>Austria</item>
    <item>Azerbaijan</item>
    <item>Bahrain</item>
    <item>Bangladesh</item>
    <item>Barbados</item>
    <item>Belarus</item>
    <item>Belgium</item>
    <item>Belize</item>
    <item>Benin</item>
    <item>Bermuda</item>
    <item>Bhutan</item>
    <item>Bolivia</item>
    <item>Bosnia and Herzegovina</item>
    <item>Botswana</item>
    <item>Bouvet Island</item>
    <item>Brazil</item>
    <item>British Indian Ocean Territory</item>
</string-array>

然後, 在 OnCreate 方法中這樣初始化 ArrayAdapter :

var countries = Resources.GetStringArray(Resource.Array.CountryArray);
this.ListAdapter = new ArrayAdapter<string>(this,
    Resource.Layout.MyListActivityItemLayout, countries);

現在的 MyListActivity 的原始碼如下:

[Activity(Label = "ListDemo", MainLauncher = true)]
public class MyListActivity : ListActivity {

    protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);

        // 獲取資源中定義的字串陣列
        var countries = Resources.GetStringArray(Resource.Array.CountryArray);
        this.ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.MyListActivityItemLayout, countries);
        this.ListView.TextFilterEnabled = true;

        this.ListView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => {
            var toast = Toast.MakeText(this.Application, ((TextView)e.View).Text, ToastLength.Short);
            toast.Show();
        };
    }
}

使用自定義 ListAdapter

在很多情況下, 還需要使用自定義的 ListAdapter , Mono for Android 版本的自定義 BaseAdapter 實現如下:

public class MyListAdapter : BaseAdapter<string> {

    private string[] _data;
    private Activity _activity;

    public MyListAdapter(Activity activity) {
        // 引用當前的 activity 是必須的, 否則貌似沒辦法呼叫 LayoutInflater
        this._activity = activity;
        // 從資源中載入陣列資料
        this._data = activity.Resources.GetStringArray(Resource.Array.CountryArray);
    }

    // 重寫 GetItemId 方法, 
    public override long GetItemId(int position) {
        return position;
    }

    // 重寫 GetView 方法, 獲取每個資料的單元格。
    public override View GetView(int position, View convertView, ViewGroup parent) {
        TextView view = convertView as TextView;
        if (view == null) {
            // 貌似只有通過 Activity 才能使用 LayoutInflactor , 
            view = (TextView)this._activity.LayoutInflater.Inflate(Resource.Layout.MyListActivityItem, null);
        }
        view.Text = this._data[position];
        return view;
    }

    // 重寫 Count 屬性, 只有 Mono for Android 才有
    public override int Count {
        get {
            return this._data.Length;
        }
    }

    // 實現 this 索引器, 這個也是 Mono for Android 才有的
    public override string this[int position] {
        get {
            return this._data[position];
        }
    }

}

從上面的程式碼可以看出, Mono for Android 提供的 BaseAdapter<T> 有著濃厚的 .Net 風格, 比如 Count 屬性, this 索引器 等, 當然, 這些對於有經驗的 .net 開發人員來說, 都是已經掌握的知識了。 使用這個自定義 Adapter 也是非常方便的, 只要用將 ListActivity 的初始化程式碼改成這樣就行:

var arrayAdapter = new MyListAdapter(this);
this.ListAdapter = arrayAdapter;
this.ListView.TextFilterEnabled = true;

相關文章