你想知道如何把多个ListView控件放到一个布局中,但是让它们在显示时表现正确吗 多个列表项?你对它们正确滚动有问题吗?这个例子将向你展示如何组合单独的ListView控件 到一个单一的ListView,并将其分割为子节,每个子节使用自己的ListAdapter。我应该澄清一下,我们实际上没有嵌套 列表视图控件,我们将在一个列表视图中使用子节,并动态填充每个列表项。 背景:这个例子假设你已经熟悉Android和Mono c#编码。我基于Wrox书中的一个例子, 专业的Android编程与Mono为Android和。net / c#。这个例子对书中的例子做了一些修改。这种方法将允许滚动行为 正常工作。最佳实践是不要在一个布局中有一个以上的ListView。这样做会导致 ListView默认显示每个列表项, 强制单独滚动每个ListView。这是非常恼人的行为,而期望的行为将是每个ListView 显示它的所有列表项,并允许父布局处理滚动。此方法将允许您实现此行为。我还扩展了图书示例,向您展示了如何处理ListView。ItemClicked事件来正确处理正确的项类型,因为我们的示例将组合多个列表项类型,每个列表项类型使用代码从它们自己的适配器中萌发。我们的布局将显示一个列表视图,为我们定义的每种不同类型的食物进行分区。首先,让我们定义我们的数据模型: 隐藏,复制Code

public class MeatType
{
private double _pricePerPound;
public MeatType(String name, String description, double pricePerPound)
{
_name = name;
_description = description;
_pricePerPound = pricePerPound;
}
public String Name
{
get { return _name; } set { _name = value; }
}
public String Description
{
get { return _description; } set { _description = value; }
}
public double PricePerPound
{
get { return _pricePerPound; } set { _pricePerPound = value; }
}
}

为了简单起见,我们还有蔬菜类和水果类,它们的结构都和肉类一样, 但是我不会在这里列出它们,因为它们的结构是相同的。接下来,我们需要一个模板来描述我们的食物类型列表项的布局。尽管我们将为每种食物类型编写单独的ListAdapter,但是在本例中适配器都可以使用相同的列表项模板,因此,我们只需要一个,FoodTypeListItem.xml。这个模板将是线性布局, 与水平方向,和三个TextView控件持有 我们的三个财产价值。收缩,复制Code

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:id="@+id/rootLayout">
<TextViewandroid:id="@+id/nameLabel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10px"android:width="100px"android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextViewandroid:id="@+id/descriptionLabel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:width="150px"android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextViewandroid:id="@+id/priceLabel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:width="50px"android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>

此模板将用于膨胀我们的列表项。每个适配器都可以调用这个模板,并以不同的方式填充它,但是外观将是相同的,从而允许接口表示的一致性。接下来,我们需要编写列表适配器,每个适配器都将扩展baseadapter>同样,为了简洁起见,我将只显示MeatTypeListAdapter, VegetableTypeListAdapter和FruitTypeListAdapter除了Type>强制类型转换。 隐藏,收缩,适配器的骨架是GetView方法。它接受给定位置的项,并创建已定义类型的视图 ,并使用项属性值填充其控件。您必须编写此方法,以正确处理计划使用的模板和数据来自的项类型。LinearLayout类型在我们的例子中,我们的观点是,如果你使用一个不同的根布局类型,甚至只是一个基本控制类型,那么您的代码应该反映这类通过改变! (LinearLayout视图),不管你的控制类型,这样你提供适当的视图类型。如果条款允许回收的代码在运行时,如果一个LinearLayout已经通过,即相同的视图类型GetView连续调用,那么通货膨胀没有必要只接下来,我们需要创建一个SectionedListAdapter处理多个列表我们想要包含在列表视图控件。在编写此适配器之前,我们需要 ListSection类来描述单独的列表子节。的 ListSection类将保存该节的文本标题、该节的列标题名和 ListAdapter,与此部分一起使用。隐藏,同样,在创建分段适配器之前,我们需要一个xml模板来描述分段标题或分隔符。 您可以简单地使用TextView来实现这一点。设置分隔符视图样式标签为"?android:attr/listSeparatorTextViewStyle" 将在分隔符视图的底部边框上放置分隔符边框线。对于这个示例,我希望分隔符也包含列标题,因此这个模板将比简单的TextView更复杂一些。 xml看起来是这样的:收缩,复制Code

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rootLayout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical">
<TextViewandroid:id="@+id/caption"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="10px"android:textAppearance="?android:attr/textAppearanceSmall"/>
<LinearLayoutandroid:id="@+id/columnHeaderLayout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"style="?android:attr/listSeparatorTextViewStyle">
<TextViewandroid:id="@+id/columnHeader1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:marginLeft="10px"android:width="100px"android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextViewandroid:id="@+id/columnHeader2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:width="150px"android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextViewandroid:id="@+id/columnHeader3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:width="50px"android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</LinearLayout>

您可以看到,我们已经设置了内部LinearLayout,它保存我们的列标题,作为listSeperatorTextViewStyle,因此整个LinearLayout得到边界线在它下面。现在我们准备创建我们的分段适配器,SectionedListAdapterHide,收缩,复制code

using Android.App;
using Android.Widget;
using Android.Views; public class SectionedListAdapter
{
private const int TYPE_SECTION_HEADER = 0;
private Context _context;
private LayoutInflater _inflater;
private List<ListSection> _sections;
public SectionedListAdapter(Context context)
{
_context = context;
_inflater = LayoutInflater.From(_context);
_sections = new List<ListSection>();
}
public List<ListSection> Sections { get { return _sections; } set { _sections = value; } } // Each section has x list items + 1 list item for the caption. This is the reason for the +1 in the tally
public override int Count
{
get
{
int count = 0;
foreach (ListSection s in _sections) count += s.Adapter.Count + 1;
return count;
}
} // We know there will be at least 1 type, the seperator, plus each
// type for each section, that is why we start with 1
public override int ViewTypeCount
{
get
{
int viewTypeCount = 1;
foreach (ListSection s in _sections) viewTypeCount += s.Adapter.ViewTypeCount;
return viewTypeCount;
}
}
public override ListSection this[int index] { get { return _sections[index]; } }
// Since we dont want the captions selectable or clickable returning a hard false here achieves this
public override bool AreAllItemsEnabled() { return false; }
public override int GetItemViewType(int position)
{
int typeOffset = TYPE_SECTION_HEADER + 1;
foreach (ListSection s in _sections)
{
if (position == 0) return TYPE_SECTION_HEADER;
int size = s.Adapter.Count + 1;
if (position < size) return (typeOffset + s.Adapter.GetItemViewType(position - 1));
position -+ size;
typeOffset += s.Adapter.ViewTypeCount;
}
return -1;
}
public override long GetItemId(int position) { return position; }
public void AddSection(String caption, String columnHeader1, String columnHeader2,
String columnHeader3, BaseAdapter adapter)
{
_sections.Add(new ListSection(caption, columnHeader1, columnHeader2, columnHeader3, adapter));
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
foreach (ListSection s in _sections)
{
// postion == 0 means we have to inflate the section separator
if (position == 0)
{
if (view == null || !(view is LinearLayout))
{
view = _inflater.Inflate(Resource.Layout.ListSeparator, parent, false);
}
TextView caption = view.FindViewById<TextView>(Resource.Id.caption);
caption.Text = s.Caption;
TextView columnHeader1 = view.FindViewById<TextView>(Resource.Id.columnHeader1);
columnHeader1.Text = s.ColumnHeader1;
TextView columnHeader2 = view.FindViewById<TextView>(Resource.Id.columnHeader2);
columnHeader2.Text = s.ColumnHeader2;
TextView columnHeader3 = view.FindViewById<TextView>(Resource.Id.columnHeader3);
columnHeader3.Text = s.ColumnHeader3;
}
int size = s.Adapter.Count + 1;
// postion < size means we are at an item, so we just pass through its View from its adapter
if (position < size) return s.Adapter.GetView(position - 1, convertView, parent);
position -= size;
}
return null;
} public override Java.Lang.Object GetItem(int position)
{
foreach (ListSection s in _sections)
{
if (position == 0) return null; // this is a separator item, dont want it instantiated
int size = s.Adapter.Count + 1;
if (position < size) return s.Adapter.GetItem(position);
position -= size;
}
return null;
}
}

正如你看到的,在这个例子中我们需要覆盖GetItem。通常不需要这样做,因为默认情况下它会返回 这(int)。但是,对于我们的分段适配器,这个[int]返回一个ListSection对象,当试图从ListView检索列表项时,它不起作用。如上所述重写此方法将迫使该方法深入到适当的子列表并返回适当的对象 需要的是填充需要容纳所有这些信息的ListView。下面的代码片段来自App. Hide的OnCreate方法。复制Code

// Fist lets create and populate the List<> instances that hold our food items
List<MeatType> meats = new List<MeatType>();
meats.Add(new MeatType("Hamburger", "Ground chuck beef", 2.76));
meats.Add(new MeatType("Sirloin", "Sliced sirloin steaks", 4.56));
List<VegetableType> veggies = new List<VegetableType)();
veggies.Add(new VegetableType("Brocolli", "Cut brocolli floretes", 1.76));
veggies.Add(new VegetableType("Carrots", "Cut peeled baby carrots", 2.18));
List<FruitType> fruits = new List<FruitType>();
fruits.Add(new FruitType("Apple", "Granny smith apples", 0.87));
fruits.Add(new FruitType("Peach", "South Carolina peaches", 1.12));
// Now we create our adapters for the item types
MeatTypeListAdapter madptr = new MeatTypeListAdapter(this, Resource.Layout.FoodTypeListItem, meats);
VegetableTypeListAdapter vadptr = new VegetableTypeListAdapter(this, Resource.Layout.FoodTypeListItem, veggies);
FruitTypeListAdapter fadptr = new FruitTypeListAdapter(this, Resource.Layout.FoodTypeListItem, fruits);
// Now we create our sectioned adapter and add its sections
SectionedListAdapter sadptr = new SectionedListAdapter(this);
sadptr.AddSection("Available Meats", "Name", "Description", "Price (lb.)", madptr);
sadptr.AddSection("Available Vegetables", "Name", "Description", "Price (lb.)", vadptr);
sadptr.AddSection("Available Fruits", "Name", "Description", "Price (lb.)", fadptr);
// Now fetch the ListView and set its adapter to the sectioned adapter
ListView foodList = FindViewById<ListView>(Resource.Id.foodList);
foodList.SetAdapter(sadptr);
foodList.ItemClick += new EventHandler<AdapterView.ItemClickEventHandler>(foodList_ItemClick);

现在进入最后一步,正确处理ItemClick事件。我们必须确保在触发ItemClick事件时查询正确的子列表。在本例中,我们将显示一个带有所单击条目细节的新布局。下面是ItemClick事件处理程序的核心。也许有更好的方法来实现这一点,我当然愿意接受任何建议,但是我没有看到明确的方法来强制转换Java.Lang。对象转换为。net对象。出于这个原因,我比较了两个ToString方法的输出。如果你的数据对象碰巧有一个自定义的ToString方法,你可能需要稍微调整一下。 隐藏,复制Code

private void foodList_ItemClick(object sender, AdapterView.ListItemClickEventArgs e)
{
SectionedListAdapter adptr = (sender as ListView).Adapter as SectionedListAdapter;
if (adptr.GetItem(e.Position != null)
{
if (adptr.GetItem(e.Position).ToString() == typeof(MeatType).ToString())
{
// Handle your code however you like here for when a meat is clicked
}
else if (adptr.GetItem(e.Position).ToString() == typeof(VegetableType).ToString())
{
// Handle your code however you like here for when a vegetable is clicked
}
else if (adptr.GetItem(e.Position).ToString() == typeof(FruitType).ToString())
{
// Handler your code however you like here for when a fruit is clicked
}
}
}

Update——我意识到,只有当您只想以某种通用的方式对单击作出反应时,这个方法才真正有用。如果你需要处理被点击的对象,事情就会变得有点棘手,不过还不算太糟。为此,首先需要创建一个包装器类来处理Java.Lang的通道。对象实例,在覆盖适配器的GetItem(int)方法时传递。首先,包装器类JavaObjectHandlerHide复制Code

using Java.Lang;
using System;
public class JavaObjectHandler : Java.Lang.Object
{
private System.Object _instance;
public JavaObjectHandler(System.Object instance) { _instance = instance; }
public System.Object Instance { get { return _instance; } }
}

Now,当我们覆盖适配器中的GetItem(int)方法时,我们将传递一个JavaObjectHandler实例,而不是默认的Java.Lang。对象实例,我们的JavaObjectHandler将包含隐藏在适配器中的数据对象。回到任何你的baseadapter>类并添加以下方法复制code

public override Java.Lang.Object GetItem(int position)
{
if (position < _items.Count)
{
return new JavaObjectHandler(_items[position]);
}
return null;
}

,因为我们已经在SectionedListAdapter中覆盖了这个方法,现在如果单击分隔符,它将传递null,或者包含我们的数据对象的底层JavaObjectHandler。现在您可以修改ItemClick事件来使用这个新的JavaObjectHandler实例,例如hide复制code

private void foodList_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
SectionedListAdapter adapter = (sender as ListView).Adapter as SectionedListAdapter;
JavaObjectHandler item = adapter.GetItem(e.Position);
if (item != null)
{
if (item.Instance is MeatType)
{
Toast.MakeText(this, "You clicked a meat: " +
(item.Instance as MeatType).Name, ToastLength.Short).Show();
}
else if (item.Instance is VegetableType)
{
Toast.MakeText(this, "You clicked a vegetable: " +
(item.Instance as VegetableType).Name, ToastLength.Short).Show();
}
else if (item.Instance is FruitType)
{
Toast.MakeText(this, "You clicked a fruit: " +
(item.Instance as FruitType).Name, ToastLenght.Short).Show();
}
}
}

这个分段适配器可以用于ListView或ListActivity类似。, History  1.0 - 2012年12月7日-一般操作发布。稍后将介绍源代码和示例项目。1.1—12/17/2012—更新以反映更高级的JavaObjectHandler的使用 ItemClick事件处理。添加示例项目到文章。Sample是为Android 4.0.3构建的。 本文转载于:http://www.diyabc.com/frontweb/news30838.html

Android使用Mono c#分段列表视图的更多相关文章

  1. Android应用开发学习之列表视图

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 列表视图我们会经常用到,可以通过两种方式来创建列表视图,一种方式是直接使用ListView组件创建,另一种方式是通过 ...

  2. 【Android】9.3 自定义列表视图的外观

    分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 自定义的列表视图通常用Resources/Layout文件夹下的axml文件中的资源来声明,适配器则通过Id去加载 ...

  3. Android之怎样使用ListView列表视图

    ListView 列表视图创建方法: (1)直接使用ListView 组件创建 (2)让Activity继承ListActivity实现 第一种:在XML中直接使用ListView 组件创建 在val ...

  4. Android应用开发学习之表格视图

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 本文我们来学习一个使用表格视图的程序,下图是该程序的运行效果: 该程序主Activity文件内容如下: packag ...

  5. Android列表视图(List View)

    Android列表视图(ListView) ListView是一个显示滚动项列表的示视图组(viewgroup),通过使用适配器(Adapter)把这些列表项自动插入到列表中.适配器比如从一个数组或是 ...

  6. Android 自学之列表视图ListView和ListActivity

    ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有列表项. 创建ListView有两种方式: 直接使用ListView创建. 让Activity继承ListActivity ...

  7. Android——列表视图(ListView)

    列表视图是android中最常用的一种视图组件,它以垂直列表的形式列出需要显示的列表项.在android中有两种方法向屏幕中添加列表视图:一种是直接使用ListView组件创建:另外一种是让Activ ...

  8. Android 用SQLite 使用 CursorLoader 中的数据填充列表视图

    我做了简单的测试应用程序基于此示例.有一个按钮,插入到数据库和列表视图的数据.都是在 MainActivity 中.在原来的代码是restartLoader() 仅从调用 onResume() ,但它 ...

  9. Android Studio [RecyclerView/列表视图]

    LinearRecyclerViewActivity.java package com.xdw.a122.recyclerview; import android.graphics.Rect; imp ...

随机推荐

  1. Google Kick Start 2020 Round C

    ac代码 A. Countdown for循环跑一跑,没啥好说的. B. Stable Wall 如果\(s_{i,j} \ne s_{i+1,j}\),那么说明\(s_{i+1,j}\)必须在\(s ...

  2. 如何利用 docker 快速部署 Mysql 服务

    docker 基础教程不再多说,这里只着重讲如何使用 docker 部署 mysql 服务 docker 拉取 访问 dockerhub,搜索关键词 mysql,我这里选择 mysql-server, ...

  3. PHP复杂变量

    eval($str="${${phpinfo()}}";)     →   可以执行phpinfo() ${phpinfo()} = {${phpindo()}} PHP复杂变量 ...

  4. java实现内网通信

    package newTest; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; ...

  5. Oracle数据库之表与表数据操作

    一.SQL语言 SQL语言分为四种,分别是:数据定义语言(DDL).数据操纵语言(DCL).事务控制语言(TCL).数据控制语言(DML). 1.1 数据定义语言(DDL) 建立.修改.删除数据库对象 ...

  6. SpringBoot版不需要配置文件注解获取当前登录用户

    本文讯(2019年3月30日 飞快的蜗牛博客)   我是一个懒人,很久不写博客,想起来看到也不一定会写,只有心血来潮的时候写写,"钱塘江上潮信来,今日方知我是我"...... 空杯 ...

  7. random模块的应用

  8. Redis必须会的知识点

    Nosql:非关系型数据库 分表分库 + 水平拆分 + mysql集群: 在Memcached的高速缓存,Mysql主从复制.读写分离的基础上,由于MyISAM使用表锁,高并发Mysql应用开始使用I ...

  9. CentOS 7使用PuppeteerSharp无头浏览器注意事项

    环境: CentOS 7.6.1810 .net core 3.1 PuppeteerSharp 2.0.0 1.如网络部稳定可以提前下载需要的chromium 下载地址:https://storag ...

  10. JVM垃圾回收行为的并行与并发

    程序的并行和并发 程序的并发(Concurrent) 在操作系统中,是指一个时间段中有几个程序都处于己启动运行到运行完毕之间,且这几个程序都是在同一个处理器_上运行. 并发不是真正意义上的“同时进行” ...