你想知道如何把多个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. 几个Graphics函数

    1.Graphics.Blit:Copies source texture into destination render texture with a shader 声明: 1.public sta ...

  2. Android反解符号表工具

    cd ~/android-ndk-r13b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin ./arm-linux-an ...

  3. 剑指 Offer 45. 把数组排成最小的数

    题目描述 输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个. 示例 1: 输入: [10,2] 输出: "102" 示例 2: 输入: ...

  4. Java获取Linux上指定文件夹下所有第一级子文件夹

    说明:需要只获得第一级文件夹目录 package com.sunsheen.jfids.studio.monitor.utils; import java.io.BufferedReader; imp ...

  5. 教会舍友玩 Git (再也不用担心他的学习)

    舍友长大想当程序员,我和他爷爷奶奶都可高兴了,写他最喜欢的喜之郎牌Git文章,学完以后,再也不用担心舍友的学习了(狗头)哪里不会写哪里 ~~~ 一 先来聊一聊 太多东西属于,总在用,但是一直都没整理的 ...

  6. TP6.0中的密码验证逻辑、验证器的使用

    目录 1. 场景一:只有一个密码框,并且是可选项,留空不修改密码,不留空则修改密码 2. 场景二:两个密码框,修改密码时有新密码.确认密码,新密码框不为空时,确认密码才验证 1. 场景一:只有一个密码 ...

  7. Java 后端开发常用的 10 种第三方服务

    请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题. 严格意义上 ...

  8. python之requests.session()使用

    背景:使用requests.session会话对象先登录至豆瓣网,再进入“我的豆瓣”. 首先说一下,为什么要进行会话保持的操作? requests库的session会话对象可以跨请求保持某些参数. 说 ...

  9. selenium中各个模块操作:下拉框、鼠标悬浮连贯、拼图拖拽操作、以及其他拖拽操作、连线操作

    1.下拉框的修改操作 方法一:定位到元素后,通过select选择对应的值 方法二:通过两次点击的方法:没有select的value属性时,采用click两次的方法去选择: click第一次后,出现下拉 ...

  10. [HDU2577]How to Type(DP)

    题目链接 题意 给一个大小写字符串,求最少敲击字符串次数,最开始和最后要求shift都是down的.如日常,大小写转换可以ctrl+z或者shift保持 up/down. 题解 两个dp数组,一个表示 ...