Android sets the pits that may be encountered in theme

  • 2021-09-12 02:01:37
  • OfStack

Discovery pit

Recently, the following error was reported when configuring the project theme:

This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR

Reason 1

Wrong writing:


<style name="AppTheme.NoActionBar">
  <item name="android:windowActionBar">false</item>
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowDrawsSystemBarBackgrounds">true</item>
  <item name="android:statusBarColor">@android:color/transparent</item>
 </style>

Among them, the theme used by AppTheme is the theme of AppCompat, and there is no android before the naming methods of windowActionBar and windowNoTitle under AppCompat, so an error is reported.

Correct writing:


<style name="AppTheme.NoActionBar">
  <item name="windowActionBar">false</item>
  <item name="windowNoTitle">true</item>
  <item name="android:windowDrawsSystemBarBackgrounds">true</item>
  <item name="android:statusBarColor">@android:color/transparent</item>
 </style>

Reason 2

If the theme is set to Theme with Actionbar and not matched with:


<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

Such mistakes can be made.

Look at the source code:

When we set up toolbar: ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar); Click on the source code to see that the source code call logic is:


public void setSupportActionBar(@Nullable Toolbar toolbar) {
  getDelegate().setSupportActionBar(toolbar);
 }

After chasing one step down, the truth came out:


public void setSupportActionBar(Toolbar toolbar) {
  if (!(mOriginalWindowCallback instanceof Activity)) {
   // Only Activities support custom Action Bars
   return;
  }
  // There will be a judgment here on whether there is any actionbar Existence, if there is a direct throw exception 
  final ActionBar ab = getSupportActionBar();
  if (ab instanceof WindowDecorActionBar) {
   throw new IllegalStateException("This Activity already has an action bar supplied " +
     "by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set " +
     "windowActionBar to false in your theme to use a Toolbar instead.");
  }

  // If we reach here then we're setting a new action bar
  // First clear out the MenuInflater to make sure that it is valid for the new Action Bar
  mMenuInflater = null;

  // If we have an action bar currently, destroy it
  if (ab != null) {
   ab.onDestroy();
  }

  if (toolbar != null) {
   final ToolbarActionBar tbab = new ToolbarActionBar(toolbar,
     ((Activity) mContext).getTitle(), mAppCompatWindowCallback);
   mActionBar = tbab;
   mWindow.setCallback(tbab.getWrappedWindowCallback());
  } else {
   mActionBar = null;
   // Re-set the original window callback since we may have already set a Toolbar wrapper
   mWindow.setCallback(mAppCompatWindowCallback);
  }
  invalidateOptionsMenu();
 }

Mainly here:


// There will be a judgment here on whether there is any actionbar Existence, if there is a direct throw exception 
final ActionBar ab = getSupportActionBar();
  if (ab instanceof WindowDecorActionBar) {
   throw new IllegalStateException("This Activity already has an action bar supplied " +
     "by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set " +
     "windowActionBar to false in your theme to use a Toolbar instead.");
  }

All right, over.

Summarize


Related articles: