你想知道如何把多个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. Unity WebGL

    路过弄了个unity Unity导出WebGL不支持c#socket和unity的network 可以用javascript的websocket实现... c#一般通过www从phpserver获取. ...

  2. 分布式事务和分布式hash

    分布式事务是什么? 分布式事务就是保证各个微服务之间数据一致,本质上就是保证不同数据库的数据一致性.一致性状态包含 强一致性,任何时刻,所有节点中数据都是一样的 弱一致性,数据更新后,只能访问到部分节 ...

  3. netty如何进行单元测试

    一种特殊的Channel 实现——EmbeddedChannel,它是Netty 专门为改进针对ChannelHandler 的单元测试而提供的. 将入站数据或者出站数据写入到EmbeddedChan ...

  4. CLTPHP 漏洞

    前言 awd小组的第一次训练 0x01 首先看一下主界面 使用的应该是PHP模板,随便翻一下找到一个注册界面 随便注册一个用户,登陆后在设置里找到一个上传点 上传我们的一句话木马 查看返回包,上传成功 ...

  5. python之unittest框架使用

    一.unittest框架 unittest属于python内置的单元测试框架. 二.unittest框架的核心概念 test case:指测试用例.unittest中提供了一个基本类TestCase, ...

  6. Django 中 a href标签 使用方法 跳转页面(Django四)

    上次我已经用Django启动了一个登录模板页面 具体过程见:Django启动我的第一个模板页面 但问题是我们只能通过监听的端口访问这一个页面,不能通过页面的一些连接跳转到其他页面如下,我们不能点击注册 ...

  7. [LeetCode]Sql系列2

    题目 1205. 每月交易II Transactions 记录表 +----------------+---------+ | Column Name | Type | +-------------- ...

  8. web网站——理论01

    LAMP的架构以及通信过程 LAMP的架构: LAMP是一个多C/S架构的平台,最初级为web客户端基于TCP/IP通过http协议发起传送,这个请求可能是动态的,也可能是静态的. 所以web服务器通 ...

  9. python的循环结构

    遍历循环 计数循环(N次)/(特定次)/字符串遍历循环 列表遍历循环/文件遍历循环......字典遍历循环等等 例子--计数循环 输出从1到6的整数,以2为步长 字符串遍历循环 列表遍历循环 文件遍历 ...

  10. redis连接池参数动态化

    有的时候要从后端获取数据,真实的key可能在参数之上做一些修改,查了下set-misc模块,set_unescape_uri命令支持变量替换 location ~ /get_redis$ {      ...