Android使用Mono c#分段列表视图
你想知道如何把多个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#分段列表视图的更多相关文章
- Android应用开发学习之列表视图
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 列表视图我们会经常用到,可以通过两种方式来创建列表视图,一种方式是直接使用ListView组件创建,另一种方式是通过 ...
- 【Android】9.3 自定义列表视图的外观
分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 自定义的列表视图通常用Resources/Layout文件夹下的axml文件中的资源来声明,适配器则通过Id去加载 ...
- Android之怎样使用ListView列表视图
ListView 列表视图创建方法: (1)直接使用ListView 组件创建 (2)让Activity继承ListActivity实现 第一种:在XML中直接使用ListView 组件创建 在val ...
- Android应用开发学习之表格视图
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 本文我们来学习一个使用表格视图的程序,下图是该程序的运行效果: 该程序主Activity文件内容如下: packag ...
- Android列表视图(List View)
Android列表视图(ListView) ListView是一个显示滚动项列表的示视图组(viewgroup),通过使用适配器(Adapter)把这些列表项自动插入到列表中.适配器比如从一个数组或是 ...
- Android 自学之列表视图ListView和ListActivity
ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有列表项. 创建ListView有两种方式: 直接使用ListView创建. 让Activity继承ListActivity ...
- Android——列表视图(ListView)
列表视图是android中最常用的一种视图组件,它以垂直列表的形式列出需要显示的列表项.在android中有两种方法向屏幕中添加列表视图:一种是直接使用ListView组件创建:另外一种是让Activ ...
- Android 用SQLite 使用 CursorLoader 中的数据填充列表视图
我做了简单的测试应用程序基于此示例.有一个按钮,插入到数据库和列表视图的数据.都是在 MainActivity 中.在原来的代码是restartLoader() 仅从调用 onResume() ,但它 ...
- Android Studio [RecyclerView/列表视图]
LinearRecyclerViewActivity.java package com.xdw.a122.recyclerview; import android.graphics.Rect; imp ...
随机推荐
- java 区块
方法区:存放staic变量,方法签名,类信息,字段等 堆:存放对象数据,string常量 栈:存放对象的引用,操作数,没逃逸但是逃逸分析且被编译器产生逃逸优化的对象数据
- Matlab摄像头视频基本处理
一.读取摄像头 1.首先保证摄像头及其驱动正确在电脑上安装 2.简单的代码显示驱动摄像头,并显示: vid = videoinput('winvideo',1); preview(vid); 3.默认 ...
- 【原创】经验分享:一个Content-Length引发的血案(almost....)
前言 上周在工作中遇到一个问题,挺有意思,这里记录一下.上周在工作中遇到一个问题,挺有意思,这里记录一下.标题起的很唬人,这个问题差点引发血案,花哥还是很严谨的一个人,后面备注了almost.... ...
- hadoop不能互相访问和linux防火墙守护进程
前言——作为装过几次集群的菜鸟,对于hadoop集群的安装还是比较有心得的:只要配置文件够好,集群配置就非常容易,否则也容易出现莫名其妙的问题!总结了一份3台机器搭建较完好的集群的一份配置文件. 在我 ...
- 深入理解Go系列一之指针变量
指针变量 基本概念 &a,代表 a 变量的内存地址 p,代表一个句柄引用(句柄由实例数据指针与实例类型指针两部分组成) ,句柄的好处是,当实例数据值改变时,不需要改动实例数据指针与实例类型指针 ...
- leetcode刷题-55跳跃游戏
题目 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 思路 贪心算法:记录每一个位置能够跳跃到的最远距离,如果 ...
- swift基本数据类型使用
swift基本数据类型的使用之一: 字符串的使用 swift String的使用 1.字符串的定义 1> 不可变字符串的定义 2> 可变字符串的定义 2.获取字符串的长度 3.字符串的拼接 ...
- Linux磁盘管理及LVM讲解(1)
硬盘接口 从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而SAS只在高端服务器上,价 ...
- MATLAB 与 Excel 接口
MATLAB 与 Excel 接口MATLAB 与 Excel 有两种接口方式:一种是通过 MATLAB 提供的 Excel 生成器,生成220 MATLAB 实用教程DLL 组件和 VBA 代码,实 ...
- Spring循环依赖的三种方式
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一 ...