1. 程式人生 > >Android設定theme中的坑

Android設定theme中的坑

歡迎各位訪問的部落格,部落格地址

配置專案主題的時候報瞭如下錯誤:

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

原因一

錯誤寫法:

<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>

其中AppTheme使用的主題是AppCompat的主題,由於AppCompat主題下的windowActionBar和windowNoTitle的命名方式前都沒有android字樣,所以報錯。

正確寫法:

<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>

原因二

如果主題設定成有Actionbar的Theme並且沒有配:

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

也會出這樣的錯誤。

看下原始碼:

在我們設定toolbar時候:((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);點進原始碼可以看到原始碼呼叫邏輯是:

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

在往下追一步,出真相了:

public void setSupportActionBar(Toolbar toolbar) {
        if (!(mOriginalWindowCallback instanceof Activity)) {
            // Only Activities support custom Action Bars
            return;
        }
        //這裡會去判有沒有actionbar存在,如果有直接拋異常
        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();
    }

主要在這裡:

//這裡會去判有沒有actionbar存在,如果有直接拋異常
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.");
        }

好了,結束。