【发布时间】:2015-07-14 18:32:01
【问题描述】:
我已设法解决片段事务后操作栏中出现额外图标的问题,但这是一个笨拙的解决方案,我想知道是否有更好的方法来解决它。
我有一个片段类层次结构,其中ContentFragment 是一个抽象片段,它占据整个屏幕(操作栏除外),它的子类提供额外的操作栏图标(通过它们各自的onCreateOptionsMenu() 和@ 987654323@ 方法)。例如。 ContentFragmentA 与 icon A 一起贡献,ContentFragmentB 与 icon B,ContentFragmentB 可能是也可能不是 ContentFragmentA 的子类(如果是,那么操作栏将同时包含 icon A 和 @987654331 @并排),等等。
最初(用户刚刚登录后)屏幕仅包含ContentFragmentA,操作栏包含icon A。当用户在应用程序中导航时,其他内容片段(或更准确地说是片段事务)被添加到后台堆栈中,并且相应地从操作栏中添加或删除图标。
在用户决定注销之前,这一切都表现得很好,这会提示应用程序清除整个回退堆栈(在最旧的事务回滚后将 ContentFragmentA 返回)并立即添加一个 LoginContentFragment,这有助于New Profile icon 到操作栏。但是此时icon A 也显示在新配置文件图标旁边,我不希望它显示;这就是我面临的问题。当用户注销时它应该会消失。
我通过像往常一样清除后台堆栈然后包含一个额外的事务来解决这个问题,该事务将ContentFragmentA 替换为带有setHasOptionsMenu(false) 的空白、无图标的内容片段,因此当空白时icon A 将消失片段被替换为Login fragment。但我觉得这很笨拙,并认为可能有更好的方法。
我尝试在ContentFragment 超类中调用Menu.clear(),在片段替换步骤中调用Activity.supportInvalidateOptionsMenu(),但似乎都不起作用。尤其是Menu.clear() 只会让所有图标消失,在操作栏中不留下任何图标。
有人知道替代方案吗?
相关代码:
ContentFragment.java:
public abstract class ContentFragment extends Fragment {
public static interface Callbacks {
public abstract void setCurrentContentFragment(ContentFragment contentFragment);
}
protected Callbacks mCallbacks;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onStart() {
super.onStart();
mCallbacks = (Callbacks)getActivity();
mCallbacks.setCurrentContentFragment(this);
}
@Override
public void onStop() {
super.onStop();
mCallbacks = null;
}
public boolean handleBackPressed() {
return false;
}
}
ContentFragmentA.java:
public abstract class ContentFragmentA extends ContentFragment {
protected abstract void handleIconATouched();
...
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (menu.findItem(R.id.icon_a) == null) {
inflater.inflate(R.menu.icon_a, menu);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.icon_a) {
handleIconATouched();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
}
BlankFragment.java:
public class BlankFragment extends LoggedInContentFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
}
在 MainActivity.java 中:
...
private void addContentFragmentNotAddingTransactionToBackStackIfCurrentFragment(ContentFragment fragment, boolean clearBackStack) {
// mCurrentContentFragment changes as the back stack is cleared, thus addToBackStack is calculated before the clearBackStack() step.
boolean addToBackStack = (false == clearBackStack && (mCurrentContentFragment != null && fragment.getClass() != mCurrentContentFragment.getClass()));
if (clearBackStack) {
clearBackStack();
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (addToBackStack) {
ft.addToBackStack(null);
}
ft.replace(R.id.container, fragment);
ft.commit();
getSupportFragmentManager().executePendingTransactions();
}
public void clearBackStack() {
while (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
}
// This is the step I would like to avoid
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, new BlankFragment());
ft.commit();
getSupportFragmentManager().executePendingTransactions();
}
...
【问题讨论】:
标签: java android android-fragments android-actionbar android-actionbar-compat