我有一个带有 NavigationDrawer 和许多片段的应用程序。我现在遇到的问题是,有时图标在工具栏中不可见。有时候他们在那里。我找不到重现此问题的正确方法。
我录制了一段视频来演示这种行为。如您所见,图标消失了,直到我关闭应用程序并重新打开它。
Video showing the effect of disappearing icons
查看右上角的工具栏。首先,没有图标。关闭应用程序并重新打开之后,图标就出现了。当我切换片段或进行其他活动并返回片段时,它们也会随机消失。
编辑:有时仅搜索图标消失,有时两个图标消失。
如上所述,这是一个带有片段的导航抽屉。每当我从导航抽屉中更改片段时,图标也必须根据显示的片段进行更改。
明智的代码如下:
MainActivity.java
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
...
/**
* {@link AppCompatActivity#onCreate(Bundle)}
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedPreferences = getSharedPreferences(Preferences.CINEMAN, Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
// Compatibility with older android versions
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
// restore the saved instance state
resolvingGoogleAPIClientError = (savedInstanceState != null && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false));
fragmentStack = new HashMap<>();
currentFragmentBackStackCount = 0;
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
decorView = this.getWindow().getDecorView();
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(this);
profilePictureImageView = navigationView.getHeaderView(0).findViewById(R.id.profilePictureImageView);
drawerHeaderMainLabel = navigationView.getHeaderView(0).findViewById(R.id.drawerHeaderMainLabel);
drawerHeaderSubLabel = navigationView.getHeaderView(0).findViewById(R.id.drawerHeaderSubLabel);
getSupportFragmentManager().addOnBackStackChangedListener(
() -> {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
toolbar.setNavigationOnClickListener(v -> onBackPressed());
} else {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
toolbar.setNavigationOnClickListener(v -> drawer.openDrawer(GravityCompat.START));
}
if (getSupportFragmentManager().getBackStackEntryCount() < currentFragmentBackStackCount) {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {
if (fragment != null && fragment.isVisible()) {
activeFragment = (AppFragment) fragment;
updateUIForActiveFragment();
break;
}
}
}
currentFragmentBackStackCount = getSupportFragmentManager().getBackStackEntryCount();
});
formatNavigationDrawerElements();
}
/**
* {@link NavigationView.OnNavigationItemSelectedListener#onNavigationItemSelected(MenuItem)}
*/
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_showtimes_by_movie) {
fragmentClass = ShowtimesByMovieFragment.class;
} else if (id == R.id.nav_showtimes_by_time) {
fragmentClass = ShowtimesByTimeFragment.class;
} else if (id == R.id.nav_showtimes_by_watchlist) {
fragmentClass = ShowtimesByWatchlistFragment.class;
} else if (id == R.id.nav_theatres) {
fragmentClass = TheatresFragment.class;
} else if (id == R.id.nav_articles) {
fragmentClass = ArticlesFragment.class;
} else if (id == R.id.nav_movies) {
fragmentClass = MoviesFragment.class;
} else if (id == R.id.nav_watchlist) {
fragmentClass = MoviesWatchlistFragment.class;
} else if (id == R.id.nav_settings) {
fragmentClass = SettingsFragment.class;
}
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
}
showAppFragmentOfClass(fragmentClass, false);
return true;
}
/**
* Show a new app fragment of class X
*
* @param appFragmentClass The class of the app fragment to show
* @param pushOnStack Flag defining if the new fragment should be pushed on the navigation stack
*/
void showAppFragmentOfClass(Class appFragmentClass, boolean pushOnStack, boolean isAnimatedTransition) {
fragmentClass = appFragmentClass;
showAppFragmentOfClass(appFragmentClass, pushOnStack, null, isAnimatedTransition);
}
void showAppFragmentOfClass(Class appFragmentClass, boolean pushOnStack) {
fragmentClass = appFragmentClass;
showAppFragmentOfClass(appFragmentClass, pushOnStack, null, false);
}
void showAppFragmentOfClass(Class appFragmentClass, boolean pushOnStack, AppFragment useThisInstance) {
fragmentClass = appFragmentClass;
showAppFragmentOfClass(appFragmentClass, pushOnStack, useThisInstance, false);
}
/**
* Show a new app fragment of class X
*
* @param appFragmentClass The class of the app fragment to show
* @param pushOnStack Flag defining if the new fragment should be pushed on the navigation stack
* @param useThisInstance If this is set, the instance will be used and not one created
*/
void showAppFragmentOfClass(Class appFragmentClass, boolean pushOnStack, AppFragment useThisInstance, boolean isAnimatedTransition) {
if (!CinemanApplication.getCurrentAppInstance().isActivityVisible()) {
return;
}
// do not reload the already active fragment
if (activeFragment != null && activeFragment.getClass().equals(appFragmentClass)) {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
return;
}
try {
if (appFragmentClass != null) {
AppFragment fragment = null;
if (useThisInstance != null) {
fragment = useThisInstance;
} else {
if (fragmentStack.containsKey(appFragmentClass.toString())) {
fragment = fragmentStack.get(appFragmentClass.toString());
} else {
try {
fragment = (AppFragment) appFragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (fragment != null) {
if (!fragmentStack.containsKey(appFragmentClass.toString()) && useThisInstance == null) {
fragmentStack.put(appFragmentClass.toString(), fragment);
}
if (fragment.shouldBeStoredAsLastActivity()) {
SharedPreferences sharedPreferences = getSharedPreferences(Preferences.CINEMAN, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(Preferences.LAST_ACTIVE_FRAGMENT, appFragmentClass.toString());
editor.apply();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
if (pushOnStack) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.addToBackStack(appFragmentClass.toString());
if (isAnimatedTransition) {
ft.setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up);
}
ft.replace(R.id.content_main, fragment, appFragmentClass.toString());
ft.commit();
} else {
fragmentManager.beginTransaction().replace(R.id.content_main, fragment, appFragmentClass.toString()).commit();
}
fragmentManager.executePendingTransactions();
if (activeFragment != null) {
if (fragment.displayCloseButton()) {
activeFragment.doNotTrack();
} else {
activeFragment.allowTracking();
}
}
activeFragment = fragment;
updateUIForActiveFragment();
}
}
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
} catch (Exception e) {
Utils.registerAppCrash(getApplicationContext());
Utils.reportAppCrash(e);
}
}
/**
* {@link AppCompatActivity#onOptionsItemSelected(MenuItem)}
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (activeFragment != null) {
return activeFragment.onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (activeFragment != null) {
activeFragment.setMenu(menu, getMenuInflater());
}
return super.onPrepareOptionsMenu(menu);
}
/**
* Helper method handling UI changes if the active fragment changes
*/
private void updateUIForActiveFragment() {
invalidateOptionsMenu();
activeFragment.allowTracking();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
if (activeFragment.forcePortraitMode()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
if (activeFragment.hasToolbarSpinner()) {
getSupportActionBar().setTitle(null);
toolbarSpinner.setAdapter(buildToolbarSpinnerMenuAdapter());
toolbarSpinner.setOnItemSelectedListener(activeFragment);
toolbarSpinner.setVisibility(View.VISIBLE);
} else {
toolbarSpinner.setAdapter(null);
toolbarSpinner.setOnItemSelectedListener(null);
toolbarSpinner.setVisibility(View.GONE);
if (activeFragment.getToolbarTitle() != null) {
getSupportActionBar().setTitle(activeFragment.getToolbarTitle());
}
}
if (activeFragment.getNavigationDrawerMenuId() >= 0) {
if (navigationView.getMenu().findItem(activeFragment.getNavigationDrawerMenuId()).isCheckable()) {
navigationView.getMenu().findItem(activeFragment.getNavigationDrawerMenuId()).setChecked(true);
navigationView.setCheckedItem(activeFragment.getNavigationDrawerMenuId());
}
}
setHomeButtonEnabled(true);
tabLayout.removeAllTabs();
tabLayout.clearOnTabSelectedListeners();
if (activeFragment.addTabs(tabLayout)) {
tabLayout.addOnTabSelectedListener(activeFragment);
tabLayout.setVisibility(View.VISIBLE);
} else {
tabLayout.setVisibility(View.GONE);
}
if (activeFragment.wantsFullscreenLayout()) {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
getSupportActionBar().hide();
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mainContentFrame.getLayoutParams();
layoutParams.setMargins(0, 0, 0, 0);
mainContentFrame.setLayoutParams(layoutParams);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(colorPrimaryDark);
}
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
getSupportActionBar().show();
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mainContentFrame.getLayoutParams();
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true);
layoutParams.setMargins(0, (int) getResources().getDimension(typedValue.resourceId), 0, 0);
mainContentFrame.setLayoutParams(layoutParams);
}
}
...
}
以及在导航抽屉中选择它时显示的片段:
MoviesFragment.java
public class MoviesFragment extends AppFragment {
...
/**
* {@link AppFragment#setMenu(Menu, MenuInflater)}
*/
@Override
boolean setMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.movies_options_menu, menu);
filterListViewMenuItem = menu.findItem(R.id.filter_list);
filterListViewMenuItem.setVisible(true);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
searchViewMenuItem = menu.findItem(R.id.search);
searchViewMenuItem.setVisible(false);
searchView = (SearchView) MenuItemCompat.getActionView(searchViewMenuItem);
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
searchView.setOnQueryTextListener(this);
searchView.setSubmitButtonEnabled(false);
searchView.setIconifiedByDefault(true);
searchView.setQueryHint(getString(R.string.movies_search));
updateMenu(menu);
return true;
}
@Override
public void updateMenu(Menu menu) {
BadgeStyle badgeStyle = new BadgeStyle(BadgeStyle.Style.DEFAULT, R.layout.custom_menu_action_item_badge, Color.parseColor("#ffffff"), Color.parseColor("#ffffff"), Color.parseColor("#b0152d"));
badgeStyle.setStroke(6);
badgeStyle.setStrokeColor(Color.parseColor("#e41e3d"));
if (selectedMovieGenreList != null && selectedMovieGenreList.size() > 0) {
ActionItemBadge.update(getActivity(), menu.findItem(R.id.filter_list), iconFilterList, badgeStyle, selectedMovieGenreList.size());
} else {
ActionItemBadge.update(getActivity(), menu.findItem(R.id.filter_list), iconFilterList, badgeStyle, null);
}
}
/**
* {@link AppFragment#onOptionsItemSelected(MenuItem)}
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.filter_list:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
openGenreFilter();
}
}, 60);
return true;
default:
return false;
}
}
}
movies_options_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/share_movie"
android:icon="@drawable/ic_share_white_24px"
android:title="@string/movie_toolbar_share_title"
android:visible="false"
app:showAsAction="always"
tools:ignore="AppCompatResource" />
<item
android:id="@+id/search"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="always"
android:title="@string/movies_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"
tools:ignore="AppCompatResource" />
<item
android:id="@+id/filter_list"
android:icon="@drawable/ic_filter"
android:showAsAction="always"
android:title="@string/filter_genre_title_selector"
app:actionLayout="@layout/custom_menu_action_item_badge"
app:showAsAction="always"
tools:ignore="AppCompatResource" />
</menu>
当片段到达前台时,我会打电话给invalidateOptionsMenu()
,因此据我了解,图标应显示在工具栏中。
我想不出我想念的是图标在那里一直显示而不是随机显示的原因。
感谢您的帮助。
答案 0 :(得分:0)
请记住要在片段的setHasOptionsMenu(true);
方法内调用onCreate()
,因为通过调用updateUIForActiveFragment()
使invalidateOptionsMenu();
内部的选项菜单无效了
答案 1 :(得分:-1)
尝试实现该片段具有自己的菜单项的片段。
例如:
创建一个Util类并添加这两个方法。
public static View addRemoveViewFromToolbar(FragmentActivity fragmentActivity, int resourceId) {
Toolbar toolbar = removeViewFromToolbar(fragmentActivity);
if (resourceId == 0) {
return null;
} else {
View view = LayoutInflater.from(fragmentActivity).inflate(resourceId, toolbar, false);
toolbar.addView(view);
return view;
}
}
public static Toolbar removeViewFromToolbar(FragmentActivity fragmentActivity) {
Toolbar toolbar = fragmentActivity.findViewById(R.id.toolbar);
if (toolbar.getChildCount() > 1) {
for (int i = 1; i <= toolbar.getChildCount(); i++) {//not remove navigation hamburger icon
toolbar.removeViewAt(1);
}
}
return toolbar;
}
在您的片段类中:
View toolbarView = Util.addRemoveViewFromToolbar(getActivity(), R.layout.toolbar_filter); // create toolbar_filter xml and add search and filter images
Imageview search = toolbarView.findViewById(R.id.img_search_view); // get widget view
您应该在此小部件中添加点击或其他事件。