读书频道 > 网站 > 网页设计 > C#开发Android应用实战——使用Mono for Android和.NET/C#
6.2.1 使用光标填充Spinner
12-12-26    奋斗的小年轻
收藏    我要投稿   
《C#开发Android应用实战——使用Mono for Android和.NET/C# 全面透彻地讲解Android应用编程知识,分析如何结合使用C#和Mono来编写在Android设备系列上运行的应用程序。在这本由多位专家联袂撰写的必备精品书...立即去当当网订购

下面的示例显示了将光标绑定到简单Spinner的过程。虽然这是一个很老套的示例,但是如果想对如何使用ICursor接口有一个基本的了解,那么该示例还是非常重要的。在撰写本书的时候,关于Android中Spinner和Cursor(Mono for Android中的ICursor)方面的文档并不是很完整,所以希望本节可以弥补这方面的空缺。

假设现在要求你创建一个允许用户查看设备中当前所有书签的应用程序。该应用程序必须列出该用户的所有书签,并且允许他从列表中选择一个书签。在仔细考虑了该任务之后,你可能会尝试使用下面所示的步骤来实现该应用程序:

(1) 使用浏览器内容提供器来查询书签。通过该内容提供器,你可以访问设备的浏览器设置,比如历史信息以及书签。

(2) 向活动添加一个Spinner控件,以便列出设备的书签。可以通过SpinnerAdapter将浏览器查询数据使用Spinner适配器链接到Spinner控件,从而列出设备的书签。

1. 建立Spinner和数据源

可以通过完成下面所示的步骤来建立该过程:

(1) 创建一个名为SpinnerExample的新Mono for Android项目。并将其标签重命名为默认活动Spinner Example。同时,将类名由通用的Activity1改为SpinnerExample也不失为一个好主意。

(2) 接下来在Main布局中为Spinner控件添加标记。在Layout目录中打开Main.axml文件,并为Spinner控件添加标记。同时也可以添加用来描述Spinner控件用途的TextView。程序清单6-1显示了Main.axml文件的相关内容。

程序清单6-1  向Main.axml布局添加一个Spinner
<?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/tvHeading"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="Welcome to the Spinner Example! Please select a
         bookmark!" />

    <Spinner android:id="@+id/spinner"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content" />

</LinearLayout>

Databinding_SpinnerCursor\Databinding_
Cursor\Resources\Layout\Resources\Layout\Main.axml

(3) 打开刚才重命名的SpinnerExample默认活动类。在该类中添加一个名为CreateSpinner()的方法。而在该方法中实现对Spinner进行数据绑定所需的操作。目前暂时保持该方法的内容为空。在创建完项目后,我们将重点介绍如何向该方法中添加合适的逻辑。

(4) 现在,在活动的OnCreate()事件中添加对新创建的CreateSpinner()方法的调用。当完成该操作后,所添加的代码应该如程序清单6-2所示。可以看到,一旦触发了活动的OnCreate()事件,将会创建Spinner,并进行数据绑定。

程序清单6-2  构建spinner create方法
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    CreateSpinner();
}

public void CreateSpinner()
{
    //TODO:  Add implementation code...
}

Databinding_SpinnerCursor\Databinding_Cursor\SpinnerSample.cs

(5) 接下来开始创建应用程序查询的数据源。此时,可以创建一个名为BookmarkCursor的属性。该属性将用来延缓加载所请求的ICursor对象。至于实际查询,则会创建一个名为GetBookmarkCursor()的函数,并返回一个ICursor对象。在该方法中可以添加适当的逻辑,以便获取填充了浏览器书签的光标对象。

(6) 最后,在属性的Get方法中检查是否有空值。如果找到空值,则调用GetBookmarkCursor()函数,并设置私有变量_BookmarkCursor。程序清单6-3举例说明了这个设置过程。

程序清单6-3  创建浏览器书签光标
private ICursor _BookmarkCursor;
public ICursor BookmarkCursor
{
    get {
         if (_BookmarkCursor == null)
         {
              _BookmarkCursor = GetBookmarkCursor();
         }
         return _BookmarkCursor;
    }
    set { _BookmarkCursor = value; }
}

public ICursor GetBookmarkCursor()
{
    return ManagedQuery(Browser.BookmarksUri,
         new String[]{Browser.BookmarkColumns.Title, Browser.BookmarkColumns
           .Url, Browser.BookmarkColumns.InterfaceConstants.ID },
         null, null, null);
}

Databinding_SpinnerCursor\Databinding_Cursor\SpinnerSample.cs

在GetBookmarkCursor()方法中添加了请求浏览器书签的查询。因为第3章已经介绍了如何使用内容提供器,所以此处不再进行深入介绍。但是需要重点注意的是你正在从设备中请求所有书签,并将这些书签的Url、ID和Title特性放置到String投影中。同时,BookmarkCursor属性使得在活动中的任何时候都可以访问ICursor对象。

最后,在开始使用ICursor对象之前还需要最后一步。为了从浏览器内容提供器中进行查询,需要向Android清单添加适当的uses-permission节点。通过使用Visual Studio工具可以非常轻易地完成该操作:

(1) 在Solution Explorer中右击项目,并选择Properties。

(2) 选择Android Manifest选项卡,如图6-4所示。

(3) 在Required permissions框中选中READ_HISTORY_BOOKMARKS权限。


 

2. 使用Spinner适配器

随着项目的正确创建以及数据源的就绪,现在可以实现CreateSpinner()方法了。在这个特殊的方法中包含了多个不同对象,但是可以将这些对象分为三个主要部分:

目标Spinner:通过使用FindViewByID()方法完成目标Spinner。它是对本节前面添加到Main.axml文件中的Spinner控件的引用。

SpinnerCursorAdapter的实例:该实例充当了目标Spinner与光标之间的桥梁。

Spinner中重复出现的数据项视图:该视图来自于Android平台所定义的其中一个默认布局。

通过使用上述三项,可以编写绑定Spinner所需的代码。如程序清单6-4所示。

程序清单6-4  实现CreateSpinner()方法
public void CreateSpinner()
{
    var targetSpinner = FindViewById<Spinner>(Resource.Id.spinner);
    SimpleCursorAdapter SpinnerAdapter = new SimpleCursorAdapter(
         this,
         Android.Resource.Layout.SimpleSpinnerItem,
         BookmarkCursor,
         new string[] { Browser.BookmarkColumns.Title },
         new int[] { Android.Resource.Id.Text1 });

    SpinnerAdapter.SetDropDownViewResource(
         Android.Resource.Layout.SimpleSpinnerDropDownItem);
    targetSpinner.Adapter = SpinnerAdapter;
    targetSpinner.Prompt = "Select...";
}

Databinding_SpinnerCursor\Databinding_Cursor\SpinnerSample.cs

在本示例中,通过targetSpinner对象获取了Spinner控件的引用。而通过使用SimpleCursorAdapter的新实例,将BookmarkCursor对象绑定到该适配器。特别是使用了默认的Android视图(Android.Resource.Layout.SimpleSpinnerItem)作为数据项视图。为了将BookmarkCursor中的Title列绑定到数据项视图,需要使用ID为Text1的子控件。

最后设置Spinner的下拉视图需要使用的目标资源。当将Spinner的适配器设置为对新创建的SpinnerAdapter的引用时,就完成了数据绑定过程。

提示:在查看该示例时,你可能会疑惑为什么我们知道将数据值绑定到控件Android.Resource.Id.Text1上。当使用默认的Android视图时,需要确定这些视图包含哪些子控件,以及在Android文档中这些控件的ID是什么,以便将数据绑定到这些控件上。

Android.Resource.Id命名空间包含了关于在本机布局中可能存在哪些子控件的提示。虽然许多工作示例利用了这些默认视图,但目前该过程需要反复试验。

完成上述代码后,可使用调试器来启动应用程序。假设一切运行正常的话,你应该可以看到如图6-5所示的屏幕。


 

3. 为Spinner添加Listener事件

假如启动并运行了该示例,如果可以单击其中一个列出的书签,并在Android浏览器中打开该书签的URL,那么该应用程序使用起来就更加方便了。可以通过使用Spinner的ItemSelected事件来实现上述功能。

对于很多任务来说,Spinner都是非常好的控件,但是在某些情况下,Spinner也具有很多的局限性。因此,在查看代码之前,需要注意两件事情。

虽然可将Spinner视为一个下拉列表,但它缺少下拉列表所具备的一个主要功能:Spinner没有未选中状态。不管什么时候Spinner被绑定,都将自动选择绑定集合中的第一项。这不仅意味着Spinner始终会显示一个选择项,还意味着当Spinner被首次加载时,Spinner列表中的第一项将不能够触发ItemSelected事件,因为它已经被选择了。当然前提是你没有手动更改选定的索引。

上面所讲的这种情况可能会带来Spinner另一个更大的缺点。因为当绑定时第一项始终被选择,所以在向用户显示视图之前Spinner将会调用ItemSelected事件。在活动视图将Spinner显示给用户之前,ItemSelected事件中所设置的任何事件都将被触发。

在本示例中,这意味着启动应用程序,绑定Spinner,然后启动Android浏览器并加载列表中第一项的URL。此时,用户看到的是一个浏览器窗口,而不是活动。这是Spinner的一个众所周知的行为,同时也是令人沮丧的处理过程。为了解决该问题,我们将使用一个局部变量来跟踪Spinner的状态,并确定是否要启动相关事件。

提示:在了解了有关使用Spinner的弊端后,你可能会问Spinner是否是完成任务所需的理想控件。这是一个应当予以关注的问题。

一般来说,当需要对没有预设值的项目列表中的单击事件进行响应时,Spinner并不是一个理想的工具。在此类情况下,ListViews和其他适配器视图可能是更好的工具。
然而,为了起到示范的作用,我们特意扩展了Spinner示例,让它来处理此类情况(虽然该示例并不是处理该问题最好的方法)。为一个项目选择适配器视图时,最好充分考虑每个选项的缺点,从而最大程度地限制诸如Spinner之类的视图可能导致的意外。

为Spinner添加Listener事件需要以下几个步骤。

(1) 首先创建一个用来跟踪Spinner状态的局部变量。为此,添加一个名为LastSpinnerSelectedPosition的私有整数字段。在Spinner的Create方法的开始处将该变量的值设为0。这样,每次重建Spinner控件时,所选中的位置始终反应数据绑定状态。

(2) 接下来,在CreateSpinner()方法中,向targetSpinner添加一个事件处理程序。请确保在该方法的最后一步完成添加操作。此时,代码应该如程序清单6-5所示。

程序清单6-5  向CreateSpinner()方法添加ItemSelected事件
int LastSpinnerSelectedPosition;

public void CreateSpinner()
{
    // Since the spinner is just being created, set this
    // tracking var to 0.
    LastSpinnerSelectedPosition = 0;

    // ...  targetSpinner binding logic as previously covered  ...

    targetSpinner.ItemSelected +=
         new EventHandler<ItemEventArgs>(SpinnerItemSelected);
}

Databinding_SpinnerCursor\Databinding_Cursor\SpinnerSample.cs

(3) 最后添加名为SpinnerItemSelected()的方法作为目标事件处理程序,同时接受一个对象以及ItemEventArgs作为参数。在该方法中可以查看是否有新项被选择。如果有,则获取目标Spinner项的URL,并启动一个新活动以弹出浏览器窗口。请参见程序清单6-6。

程序清单6-6  实现ItemSelected()事件
public void SpinnerItemSelected(object sender, ItemEventArgs e)
{
    var CurrentSpinner = ((Spinner)sender);
    var CurrentSelectedIndex = CurrentSpinner.SelectedItemPosition;

    if (CurrentSelectedIndex != LastSpinnerSelectedPosition)
    {
         //  The Selected item in a spinner is actually the
         //  underlying cursor object w/ the position set to the
         //  appropriate index.  Cast to ICursor to access.
         ICursor selectedItem = (ICursor)CurrentSpinner.SelectedItem;

         var URLColumnIndex = selectedItem.GetColumnIndex(
              Browser.BookmarkColumns.Url);
         var URL = selectedItem.GetString(URLColumnIndex);

         //  In order to open a new browser, we need to create the appropriate
         //  intent and then start a new activity using that intent.
         Intent BrowserIntent = new Intent(Intent.ActionView);
         BrowserIntent.SetData(Android.Net.Uri.Parse(URL));

         StartActivity(BrowserIntent);

         LastSpinnerSelectedPosition = CurrentSelectedIndex;
    }
}
Databinding_SpinnerCursor\Databinding_Cursor\SpinnerSample.cs

在该方法中,首先进行相关检查,以确保Spinner的状态不是最初所设置的状态。这样将可以防止OnCreate()方法过早启动选定项事件。然后,通过使用Spinner的SelectedItem属性查找所选Spinner项的URL值。该项表示与所选项对应的BookmarkCursor中的位置。

最后创建BrowserIntent,并将其数据设置为目标URL。这样就允许我们创建一个新活动,而该活动打开浏览器应用程序并链接到正确的URL。完成上述代码后,应该可以打开Spinner示例并查看它的工作过程,如图6-6所示。


 

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站