安卓 - 标签页、地图视图和标签页内的活动

11
我们正在编写一个应用程序,其中有四个选项卡:地图、人物、地点和事件。 应用程序中的人物、地点和事件显示为地图上的图标。默认情况下,人物、地点和事件选项卡分别显示一个自定义渲染的列表视图,显示所有人物、地点和事件。

alt text http://web6.twitpic.com/img/37202700-f92052dc474b74e1760edda1c47f6940.4adcb134-scaled.png

现在,每个选项卡都有一个意图作为其内容,以启动相应的活动。例如,有一个MapTabActivity扩展了MapActivity,一个ShowPeopleListActivity显示人员列表,等等。

我看到很多StackOverflow的问题/答案,说由于TabHost的设置方式有各种限制,最好不要使用活动作为选项卡的内容。例如,无法启动新活动并使其取代选项卡中现有的活动,而可以将视图替换为不同的视图。

现在,我面临抉择。我们(不管是好是坏)花了相当多的时间来让这个应用程序按照当前结构正常运行,其中活动作为选项卡的内容。当单击与人、地点或事件对应的图标时,它会触发一个 VIEW Intent,该 Intent 对应于该对象的 URI;然后由一个 Activity 接收并显示该对象。同样的机制在地图和单独的列表中都起作用。我们真的很喜欢这种松散耦合方式;我们只需给出 VIEW 命令和指向人/地点/事件的 URI,它就会自动带我们到正确的活动中。当然,启动的活动覆盖了选项卡视图,而不是出现在其中,但我们愿意接受这一点。
但有一个问题:从 Show 活动返回地图时,我们想回到以该人、地点或事件为中心的地图。我们可以启动一个新的活动来再次显示地图,但现在选项卡的内容变成了地图活动,加上 Show 活动以及活动堆栈中的新地图活动;考虑到地图活动的资源密集型特性,我猜这不是理想的方法。
我想问一下,是否有一个好的教程可以展示如何使用TabHost完成复杂任务?我看过HelloTabWidget;我正在寻找比这更复杂的东西。我担心如果我们切换到基于View的方式,我们将不得不进行大量的清理工作来拦截所有返回事件,尝试切换视图等,以及强烈耦合我们的程序,这是我们不想要的。任何关于前进方向的建议都将非常感激。我们是Android新手,所以我们正在尝试遵循已经建立的最佳实践,但当我们看到的少数示例对我们的用例来说太简单时,这很困难。
3个回答

8
有一个好的实践是为您的选项卡拥有一个活动和多个视图。但是,这意味着您必须小心处理选定的选项卡,每个选项卡视图的不同菜单和上下文菜单等。
“我想问的是,是否有一个很好的教程展示如何使用TabHost执行复杂任务?我看过HelloTabWidget; 我正在寻找比这更复杂的东西。”
我在我的博客上写了一个稍微更好的教程,演示了一个交互式ListView和MapView作为选项卡。 这是链接:Android Tabs with interacting map and list views 基本原理是要有一个类似于HelloTabWidget教程中的布局,使您的活动从MapActivity扩展,从XML提取tabhost并确保在tabhost上调用setup()。 之后,添加视图作为选项卡内容,选项卡侦听器等都是相同的。
这里是该类的一个简短起点:
public class TabbedListMapActivity extends MapActivity {

private ListView listView;
private MapView mapView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tabHost = (TabHost) findViewById(android.R.id.tabhost);

    // setup must be called if not a TabActivity
    tabHost.setup();

    // setup list view
    listView = (ListView) findViewById(R.id.list);

    // setup map view
    mapView = (MapView) findViewById(R.id.mapview);

    // add views to tab host
    tabHost.addTab(tabHost.newTabSpec("List").setIndicator("List").setContent(new TabContentFactory() {
        public View createTabContent(String arg0) {
            return listView;
        }
    }));
    tabHost.addTab(tabHost.newTabSpec("Map").setIndicator("Map").setContent(new TabContentFactory() {
        public View createTabContent(String arg0) {
            return mapView;
        }
    }));
}

...


现在,这是一个很棒的答案!谢谢Josh,你救了我的一天。 - Fabio Milheiro

8
我看到许多关于TabHost的StackOverflow问题/答案,由于不同限制在TabHost设置中,最好不要使用活动作为选项卡的内容。
作为反活动选项卡联盟(AATA)自任主席,这当然是我的立场。
当单击对应于人,地点或事件的图标时,它会在相应对象的URI上触发VIEW Intent;这被一个Activity捕获,然后显示该对象。
请注意,这与将活动作为选项卡内容没有任何关系。
我们可以启动新活动以再次显示地图,但现在我们具有选项卡的地图活动内容,加上显示活动,再加上活动堆栈中的新地图活动;考虑到地图活动的资源使用情况,我猜这不是理想的方法,如果可能的话,我会避免它。
我担心如果切换到基于View的操作方式,我们将不得不做很多维护工作来拦截所有后退事件,尝试切换视图等等,以及以我们不想要的方式强烈耦合我们的程序。
这根本不符合您先前所写的内容。在使用Views作为选项卡内容和使用Activities作为选项卡内容之间,您的“后退事件”不会有任何变化。此外,这与您描述的“松散耦合”模式毫无关系--在选项卡中的视图列表中单击图标与在活动中的视图列表中单击图标没有任何区别。
只需让您的Show activity告诉您的主要activity显示特定位置,然后Show activity可以finish()。最简单的方法是在主要activity中广播一个Intent并注册BroadcastReceiver。收到此Intent后,主Activity将更新地图并将其设置为当前选项卡。当然,如果您的主要activity使用Views作为选项卡内容,则此方法更简单。
现在,如果您尝试改进应用程序,使导航在选项卡中不会启动另一个活动,而是将事物保留在自己的选项卡中...那就是完全不同的问题了。

好的,我明白你的观点,如果我们将所有意图设置相同,并启动Show activity,则返回事件处理方式完全相同。因此,我想真正的复杂性(和回退事件痛苦)可能是如果我们以编程方式切换选项卡的内容而不是启动意图。例如,“People”选项卡通常显示人员列表,但当单击给定人员时,会告知其切换到“Show person”视图。在这种情况下,我们需要自己处理视图堆栈? - I82Much
另外,如何在选项卡中放置一个地图而不将活动作为选项卡的内容?这是否可能? - I82Much
关于你的第一条评论,是的,你需要自己进行堆栈管理。关于你的第二个评论,据我所知是可以的。将你的主要活动设置为MapActivity而不是TabActivity。TabActivity为你自动调用setup()方法并在添加任何TabSpecs之前需要自行完成。然后,MapActivity会为你提供放置地图选项卡所需的功能。可能会出现问题,但我认为它应该可以正常工作。 - CommonsWare

1
例如,无法启动一个新的活动并使其取代现有选项卡中的现有活动,而可以使用不同的视图切换出视图。
我认为这并非不可能。我尝试了这个想法,并写了一篇博客article解释了我所做的事情。在文章末尾,我包含了一个示例代码项目,展示了我学到的一些有趣的东西。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接