読者です 読者をやめる 読者になる 読者になる

Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

Xamarin.Android の ListView で Item を追加、削除したい(CustomAdapter)

Xamarin Xamarin.Android

こんにちは。エクセルソフトの田淵です。

先日はまずは一番シンプルな単一行の SimpleListItem1 をセルにした ListView にデータを追加したり削除したりしました。

ytabuchi.hatenablog.com

今回は独自のセルを用意してデータ追加、削除を行ってみます。こんな感じです。

f:id:ytabuchi:20160819130200g:plain:w300

サンプルは以下に置いておきました。

github.com

セルの CustomView を作成

Android の ListView には Adapter とセルの View が必要です。公式ページ の Sample Code「CustomRowView」をベースにしています。

最初に View を用意します。

View は普通に Layout axml です。新規にレイアウトを作成し、任意のレイアウトを組んでください。今回は左に ImageView、右に縦に TextView を2つ並べ、一番右側に iOS っぽい矢印を入れてます。

こんな感じ。RelativeLayout で最初に ImageView を配置。2つの TextViewlayout_toRightOf="@+id/Image"layout_below="@id/NameText" を使って並べていきます。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:p1="http://schemas.android.com/apk/res/android"
    p1:layout_width="match_parent"
    p1:layout_height="match_parent"
    p1:id="@+id/relativeLayout1">
    <ImageView
        p1:src="@drawable/Icon"
        p1:layout_width="64dp"
        p1:layout_height="64dp"
        p1:paddingRight="8dp"
      
  p1:paddingLeft="8dp"
        p1:id="@+id/Image" />
    <TextView
        p1:text="Name"
        p1:textAppearance="?android:attr/textAppearanceLarge"
        p1:layout_width="match_parent"
        p1:layout_height="wrap_content"
        p1:id="@+id/NameText"
        p1:layout_toRightOf="@+id/Image"
        p1:paddingTop="8dp"
        p1:paddingRight="32dp" />
    <TextView
        p1:text="Age"
        p1:textAppearance="?android:attr/textAppearanceMedium"
        p1:layout_width="match_parent"
        p1:layout_height="wrap_content"
        p1:layout_toRightOf="@+id/Image"
        p1:layout_below="@id/NameText"
        p1:id="@+id/AgeText"
        p1:paddingRight="32dp" />
    <TextView
        p1:text="&gt;"
        p1:textAppearance="?android:attr/textAppearanceMedium"
        p1:layout_width="wrap_content"
        p1:layout_height="wrap_content"
        p1:id="@+id/RightArrow"
        p1:layout_alignParentRight="true"
        p1:layout_centerVertical="true"
        p1:padding="16dp" />
</RelativeLayout>

RelativeLayout については こちらの記事 が詳しいです。

BaseAdapter のクラスを作成

CustomAdapter は BaseAdapter<T> を継承して作成しますので、先ほど作成した CustomView の各項目に割り当てる型を用意します。今回は Image 1、string *2 なので次の TableItem.cs を用意しました。

public class TableItem
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int ImageResourceId { get; set; }
}

Image は今回 Xamarin のサンプルに習い .SetImageResource(int resId) を使用したので int で用意しましたが、.SetImageBitmap(Android.Graphic.Bitmap bm).SetImageURI(Android.Net.Uri uri) を使用する場合は適切な型を指定します(すみません。Android.Net.Uri はまだ使い方が良く分かってなく…)。

CustomAdapter を作成

クラスを作成し、BaseAdapter<TableItem> を継承します。

f:id:ytabuchi:20160819133229p:plain:w450

Visual Studio であれば、必要なメソッドを用意してくれますので、それぞれに実装します。Xamarin のサンプルに習い次のように実装しました。

public class CustomListAdapter : BaseAdapter<TableItem>
{
    List<TableItem> items;
    Activity context;
        
    public CustomListAdapter(Activity context, List<TableItem> items)
    {
        this.context = context;
        this.items = items;
    }        

    public override long GetItemId(int position)
    {
        return position;
    }
    public override TableItem this[int position]
    {
        get { return items[position]; }
    }
    public override int Count
    {
        get { return items.Count; }
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var item = items[position];

        View view = convertView;
        if (view == null) // no view to re-use, create new
            view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);

        // BaseAdapter<T>の対応するプロパティを割り当て
        view.FindViewById<TextView>(Resource.Id.NameText).Text = item.Name;
        view.FindViewById<TextView>(Resource.Id.AgeText).Text = item.Description.ToString();
        view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);

        return view;
    }
}

GetView メソッド内で、TableItem のプロパティをそれぞれ割り当てます。

Activity で CustomAdapter を使う

ソースの List を用意して先ほど作った CustomListAdapter(Activity context, List<TableItem> items)インスタンス化して ListView の Adapter に指定します。

// ソースのListにアイテムを追加
tableItem.Insert(0, new TableItem()
{
    Name = "item_1",
    Description = "Description_1",
    ImageResourceId = images[4]
});

// CustomAdapterを作成して適用
var customAdapter = new CustomListAdapter(this, tableItem);
listView.Adapter = customAdapter;

データの追加、削除は、ソースの List に対して行い、Adapter に変更を通知してあげると良いそうです。(@Santea3173 さん、ありがとう!!)

ボタンをタップするとデータを追加したり削除したりする部分はこんな感じです。

var addButton = FindViewById<Button>(Resource.Id.customListViewAddButton);
addButton.Click += (sender, e) =>
{
    var rdm = new Random();
    // ソースのListにアイテムを追加し、Adapterに変更を通知して画面を更新させる
    tableItem.Insert(0, new TableItem() 
    {
        Name = "item_" + rdm.Next(), 
        Description = "Description_" + rdm.Next(), 
        ImageResourceId = images[rdm.Next(0, 8)]  // *1
    });
    customAdapter.NotifyDataSetChanged();

};

var deleteButton = FindViewById<Button>(Resource.Id.customListViewDeleteButton);
deleteButton.Click += (sender, e) =>
{
    if (tableItem.Count > 0)
    {
        // ソースのListからアイテムを削除し、Adapterに変更を通知して画面を更新させる
        tableItem.Remove(tableItem[tableItem.Count - 1]);
        customAdapter.NotifyDataSetChanged();
    }
};

*1 ですが、Randomで参照するので作成した画像データを元に int[] に Resource.Drawable.ramen1 などを入れておいてます。

ListView もそんなに怖くないですね。

ちょっとビビっていましたが、Android の ListView は大丈夫そうです。次は CardView か RecyclerView とかにチャレンジしたいですね。

Xamarin 気になった方は

是非 ダウンロード して触ってみてください。Visual Studio 2015 をご利用の方は Update 3 にアップデートする際にカスタムインストールで Xamarin を追加しましょう。 学習用リソースJXUG リンクページ に参考資料を纏めてますので併せてどうぞ。

Xamarin の導入支援サービスを始めました。ベースは基本的なアプリを一緒に作ることで Xamarin を使えるようになって頂く内容ですが、ご要望に応じて講習内容のカスタマイズも可能です。詳しくは田淵までお問い合わせください(^^)

ytabuchi.hatenablog.com

Xamarin の情報が欲しい方はこのブログも購読いただいたり、私のTwitterアカウントをフォローいただいたりすると嬉しいです。

私が所属している エクセルソフト の宣伝を少しさせてください。弊社は開発者向けの様々なソフトウェアを扱っています。おなじみの ReSharper (JetBrains)、 や Atlassian の JIRA, Confluence、Office/PDF ファイルを .NET/Java で操作するライブラリ Aspose(アスポーズ)Windows アプリ、Web ページ、iOS/Android アプリの UI テストができる TestComplete などお勧めです(^^) また、Visual Studio Professional/Enterprise with MSDN も販売してますし、日本で売っていない海外のソフトウェア、開発ツールなどを弊社経由で日本円で購入頂くことも可能です。ご興味あれば 弊社ページ を覗いてみてください。

以上です。