- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这是我的问题。我有一个应用程序,我在其中使用带有选项卡的 ActionBar Sherlock,带有选项菜单的 fragment 。每次我旋转模拟器时,都会为所有 fragment 添加菜单,即使是隐藏/删除的 fragment (我都试过了)。
这是设置:一个 FragmentActivity,它有一个带
的 ActionBar final ActionBar bar = getSupportActionBar();
bar.addTab(bar.newTab()
.setText("1")
.setTabListener(new MyTabListener(new FragmentList1())));
bar.addTab(bar.newTab()
.setText("2")
.setTabListener(new MyTabListener(new FragmentList2())));
bar.addTab(bar.newTab()
.setText("3")
.setTabListener(new MyTabListener(new FragmentList3())));
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowHomeEnabled(true);
bar.setDisplayShowTitleEnabled(true);
所有选项卡都使用相同的监听器:
private class MyTabListener implements ActionBar.TabListener {
private final FragmentListBase m_fragment;
public MyTabListener(FragmentListBase fragment) {
m_fragment = fragment;
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
FragmentManager fragmentMgr = ActivityList.this.getSupportFragmentManager();
FragmentTransaction transaction = fragmentMgr.beginTransaction();
transaction.add(R.id.frmlyt_list, m_fragment, m_fragment.LIST_TAG);
transaction.commit();
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
FragmentManager fragmentMgr = ActivityList.this.getSupportFragmentManager();
FragmentTransaction transaction = fragmentMgr.beginTransaction();
transaction.remove(m_fragment);
transaction.commit();
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
FragmentListBase 的每个子类都有自己的菜单,因此所有 3 个子类都有:
setHasOptionsMenu(true);
和适当的
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d(TAG, "OnCreateOptionsMenu");
inflater.inflate(R.menu.il_options_menu, menu);
}
当我运行该应用程序时,我可以看到针对所有不同的 fragment 多次调用了 onCreateOptionsMenu。
我完全被难住了。
我尽量贴出尽可能多的代码而不至于让人不知所措,如果您发现有什么地方遗漏了,请指教。
[编辑]我添加了更多日志记录,结果发现该 fragment 在旋转时被附加了两次(或更多)。我注意到的一件事是,除仅调用一次的 onCreate() 方法外,所有内容都被多次调用。
06.704:/WindowManager(72): Setting rotation to 0, animFlags=0
06.926:/ActivityManager(72): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=35}
07.374:/FragmentList1(6880): onAttach
07.524:/FragmentList1(6880): onCreateView
07.564:/FragmentList1(6880): onAttach
07.564:/FragmentListBase(6880): onCreate
07.564:/FragmentList1(6880): OnCreateOptionsMenu
07.574:/FragmentList1(6880): OnCreateOptionsMenu
07.604:/FragmentList1(6880): onCreateView
[编辑 2]
好的,我开始回溯到 Android 代码并在此处找到这部分(我对其进行了编辑以缩短这篇文章)。
/com_actionbarsherlock/src/android/support/v4/app/FragmentManager.java
public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu) {
f.onCreateOptionsMenu(menu, inflater);
}
}
}
问题是 mAdded 中确实有多个 FragmentList1 实例,因此 onCreateOptionsMenu() 方法“正确”被调用了 3 次,但针对的是 FragmentList1 类的不同实例。我不明白的是为什么要多次添加该类...但这是一个很好的线索。
最佳答案
我似乎找到了问题所在。我说问题是因为在众多菜单之上,现在还有一个异常。
1) 调用
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
在调用 addTab() 之后 会产生调用 onTabSelected() 的副作用。然后,我的 TabListener 会将 FragmentList1 添加到 FragmentManager
2) 旋转设备会按预期销毁 Activity,但不会销毁 Fragment。当旋转后创建新 Activity 时,它会做两件事:
调用 onTabSelected(通过 setNavigationMode())将执行以下代码:
if (null != fragmentMgr.findFragmentByTag(m_fragment.LIST_TAG)) {
transaction.attach(m_fragment);
transaction.show(m_fragment);
}
else {
transaction.add(R.id.frmlyt_list, m_fragment, m_fragment.LIST_TAG);
}
基本上,如果 fragment 已经在 FragmentManager 中,则无需添加,只需显示即可。但问题就在这里。这不是同一个 fragment !它是由 Activity 的早期实例创建的 Fragment。所以它会尝试附加并显示这个新创建的 fragment ,这会导致异常
解决方案。
要解决所有这些问题,需要做一些事情。
1) 我将 setNavigationMode() 移到 addTab() 上方。
2) 这就是我现在创建标签的方式:
FragmentListBase fragment = (FragmentListBase)fragmentMgr.findFragmentByTag(FragmentList1.LIST_TAG_STATIC);
if (null == fragment) {
fragment = new FragmentList1();
}
bar.addTab(bar.newTab()
.setText("1")
.setTabListener(new MyTabListener(fragment)));
因此,在创建 Activity 时,我必须检查 Fragment 是否已经在 FragmentManager 中。如果是,我使用这些实例,如果不是,那么我创建新的实例。这对所有三个选项卡都完成了。
您可能已经注意到有两个相似的标签:m_fragment.LIST_TAG 和 FragmentList1.LIST_TAG_STATIC。啊,这真可爱……(<- 讽刺)
为了以多态方式使用我的 TagListener,我在基类中声明了以下非静态变量:
public class FragmentListBase extends Fragment {
public String LIST_TAG = null;
}
它是从后代内部分配的,允许我在 FragmentManager 中查找 FragmentListBase 的不同后代。
但我还需要在创建特定后代之前搜索它们(因为我需要知道是否必须创建它们),所以我还必须声明以下静态变量。
public class FragmentList1 extends FragmentListBase {
public final static String LIST_TAG_STATIC = "TAG_LIST_1";
public FragmentList1() {
LIST_TAG = LIST_TAG_STATIC;
};
}
我只想说我很失望没有人想出这个简单而优雅的解决方案(<-更多讽刺)
非常感谢 Jake Wharton 花时间帮我看这个:)
关于android - 使用选项卡在 ActionBar 中调用 onCreateOptionsMenu 的次数太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7224415/
在 Android 的 API > 19 中是否有任何方法可以获取可移动 SD 卡的路径? 与外部 SD 卡一样,我们有 Environment.getExternalStorageDirectory
一些 Android 设备有 microSD(或其他存储卡)插槽,通常安装为 /storage/sdcard1 据我所知,自 Android 4.4 起 Google 限制了对此内存的访问,并在 An
我使用 Java Card 2.1.2 SDK 和 GPShell 作为与设备通信的方式在 Java Card 上构建一个项目。我从 GpShell 测试了 helloworld 示例,并成功发送了
我开发了一个应用程序,它有一个来电接收器,它适用于所有手机。一位用户有一部双 SIM 卡安卓手机。该应用程序适用于第一张 SIM 卡。但是当有人调用他的第二张 SIM 卡时,我们的应用程序不会被调用。
我有一个带预览的文件输入。 这是笔 Codepen 我想强制高度,我无法理解我该怎么做。我想将此组件的高度固定为 300px(示例),我还需要保持加载图像的正确纵横比,用灰色背景填充空白。现在我保持宽
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我正在使用此代码访问 SD card : import os from os.path import join from jnius import autoclass #from android.pe
我正在为数据记录设备编写固件。它以 20 Hz 的频率从传感器读取数据并将数据写入 SD 卡。但是,向SD卡写入数据的时间并不一致(大约200-300 ms)。因此,一种解决方案是以一致的速率将数据写
我正在使用以下代码将视频放到网站上,但是在垂直方向上,手机屏幕上只能看到视频的左半部分 我不是网络开发人员。有人可以告诉我确切的内容吗,如何使其正确放置在手机屏幕上? 是在youtube iframe
我正在使用 Vuetify 1.5 和 Vuetify 网格系统来设置我的布局。现在我有一个组件 HelloWorld我将其导入到我的 Parent 中成分。我已经在我的 HelloWorld 中设置
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我正在使用玩家卡设置 Twitter 卡。它可以在预览工具中运行,但文档说它需要在“twitter.com 现代桌面浏览器? native iOs 和 Android Twitter 应用程序?mob
任何旧的 GSM 兼容 SIM 卡(3G USIM 的奖励)。 我想我需要一些硬件?谁能为业余爱好者推荐一些便宜的东西,以及一些更专业的东西? 我认为会有一个带有硬件的 API 的完整文档,所以也许这
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我记得前一段时间读到有 cpu 卡供系统添加额外的处理能力来进行大规模并行化。任何人都有这方面的经验和任何资源来研究项目的硬件和软件方面吗?这项技术是否不如传统集群?它更注重功率吗? 最佳答案 有两个
我检查外部存储是否已安装并且可用于读/写,然后从中读取。我使用的是确切的官方 Android 示例代码 ( from here )。 它说外部存储未安装。 getExternalFilesDir(nu
在 Android 2.1 及更低版本中,Android 应用程序可以请求下载到 SD 卡上吗?另外我想知道应用程序是否可以请求一些包含视频的文件夹下载到 SD 卡上?以及如何做到这一点? 提前致谢。
我们编写了一个 Windows 设备驱动程序来访问我们的自定义 PCI 卡。驱动程序使用 CreateFile 获取卡的句柄。 我们最近在一次安装中遇到了问题,卡似乎停止工作了。我们尝试更换卡(更换似
有些新设备(例如 Samsung Galaxy)带有两个 SD 卡。我想知道是否有任何方法可以确定设备是否有两张 SD 卡或一张 SD 卡。谢谢 最佳答案 我认为唯一的方法是使用 检查可用根的列表 F
我正在尝试将文件读/写到 SD 卡。我已经尝试在我的真实手机和 Eclipse 中的模拟器上执行此操作。在这两种设备上,对/mnt/sdcard/或/sdcard 的权限仅为“d--------”,我
我是一名优秀的程序员,十分优秀!