Xamarin Android ListView

Xamarin Android ListView

之前写 WPF 的时候,自定义 ListView 可以非常轻松的就实现,无论是通过DataTemplate还是 ItemTemplate都可以达到预期效果,但是 Xamarin Android 就比较复杂了。

创建自定义布局

创建自定义行布局
四个内置行视图是非常简单。 要显示更复杂的布局 (如电子邮件或推文或联系信息的列表) 将需要自定义视图。 自定义视图通常声明为 AXML 文件资源/布局目录,然后再加载,使用其资源的自定义适配器的 Id。 该视图可以包含任意数量的显示类 (如 TextViews、 ImageViews 和其他控件) 使用自定义颜色、 字体和布局。

此示例与前面的示例通过多种方式不同:

继承自 Activity,而不 ListActivity。 你可以为任何自定义行 ListView,但也可以在包含其他控件 Activity 布局 (如标题、 按钮或其他用户界面元素)。 此示例将上面的标题 ListView 来说明。

屏幕; 需要一个 AXML 布局文件在前面的示例 ListActivity 不需要的布局文件。 包含此 AXMLListView 控制声明。
需要一个 AXML 布局文件,可呈现每个行。 此 AXML 文件包含自定义字体和颜色设置的文本和图像控件。
使用可选的自定义选择器 XML 文件选择此项时设置的行的外观。

ItemClick 必须以不同的方式声明 (事件处理程序附加到 ListView.ItemClick 而不是重写 OnListItemClick 中 ListActivity)。

这些更改下面详细介绍,开始创建活动的视图和自定义行视图,然后介绍对适配器和活动来呈现它们的修改。
将 ListView 添加到活动布局

因为 HomeScreen 不再继承 ListActivity 它没有默认视图中,因此必须为 HomeScreen 的视图创建布局 AXML 文件。 对于此示例,该视图将有一个标题 (使用 TextView) 和一个 ListView 以显示数据。 在中定义布局 Resources/Layout/HomeScreen.axml 文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/Heading"
android:text="Vegetable Groups"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#00000000"
android:textSize="30dp"
android:textColor="#FF267F00"
android:textStyle="bold"
android:padding="5dp"
/>
<ListView android:id="@+id/List"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#FFDAFF7F"
/>
</LinearLayout>

使用的好处 Activity 与自定义布局 (而不是 ListActivity) 在于能够将其他控件添加到屏幕上,如标题 TextView 在此示例中。
创建自定义行布局
另一个 AXML 布局文件需包含会在列表视图中显示每个行的自定义布局。 在此示例中的行,将有绿色背景、 棕色、 文本和右对齐图像。 Android XML 标记来声明此布局中所述 Resources/Layout/CustomView.axml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFDAFF7F"
android:padding="8dp">
<LinearLayout android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/Text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic"
/>
<TextView
android:id="@+id/Text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#FF267F00"
android:paddingLeft="100dip"
/>
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:layout_alignParentRight="true" />
</RelativeLayout >

而自定义行布局可以包含许多不同的控件,滚动性能可能受到复杂的设计和使用映像 (尤其是如果他们有要通过网络加载)。 有关解决滚动性能问题,请参阅 Google 的文章了解详细信息。
引用自定义行视图
自定义适配器示例的实现 HomeScreenAdapter.cs。 关键方法是 GetView,它会加载自定义 AXML 使用的资源 ID Resource.Layout.CustomView,然后在每个视图,然后再返回它在控件上设置属性。 完整的适配器类所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class HomeScreenAdapter : BaseAdapter<TableItem> {
List<TableItem> items;
Activity context;
public HomeScreenAdapter(Activity context, List<TableItem> items)
: base()
{
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);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
return view;
}
}

引用活动中自定义的 ListView
因为 HomeScreen 类现在继承自 Activity、ListView 要保存对 AXML 中声明的控件的引用的类中声明字段:

ListView listView;

然后,类必须加载活动的自定义布局 AXML 使用 SetContentView 方法。 然后,它可以找到 ListView 布局中的控件然后创建并分配该适配器并分配的单击处理程序。 OnCreate 方法中的代码如下所示:

1
2
3
4
5
6
SetContentView(Resource.Layout.HomeScreen); // loads the HomeScreen.axml as this activity's view
listView = FindViewById<ListView>(Resource.Id.List); // get reference to the ListView in the layout

// populate the listview with data
listView.Adapter = new HomeScreenAdapter(this, tableItems);
listView.ItemClick += OnListItemClick; // to be defined

最后 ItemClick 必须定义处理程序; 在这种情况下它只是显示 Toast 消息:

1
2
3
4
5
6
void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
var listView = sender as ListView;
var t = tableItems[e.Position];
Android.Widget.Toast.MakeText(this, t.Heading, Android.Widget.ToastLength.Short).Show();
}

评论