Android技能之-setSupportActionBar(toolbar)的那點事

伴隨着Android的主題(theme)越來越多之後,記清如何使用以及怎麼使用、使用後的效果如何,並非一件短時間裏就能非常熟練的掌握好,那麼關於主題中的ActionBar,今天這邊做一個曾遇到的衝突記錄

當我們選擇創建一個Empty Activity的App項目時,默認生成的AndroidManifest.xml內容如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxx.xxx.xxx">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

在這裏,我們應該注意到默認的App主題爲android:theme="@style/AppTheme"
那麼今天的問題來了!
回憶到曾經某個項目因爲嫌棄系統自帶的Actionbar不符合需求之後,那麼重定義就免不了了,在重定義使用Actionbar的時候,因使用了API接口setSupportActionBar(@Nullable Toolbar toolbar),導致引發異常崩潰

E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.itsdf07.app.mvp, PID: 26401
        "java.lang.RuntimeException: Unable to start activity ComponentInfo{com.itsdf07.app.mvp/com.itsdf07.app.mvp.main.MainActivity}: java.lang.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."
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3194)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
        at android.app.ActivityThread.-wrap12(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
        at android.os.Handler.dispatchMessage(Handler.java:108)
        at android.os.Looper.loop(Looper.java:166)
        at android.app.ActivityThread.main(ActivityThread.java:7425)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
        "Caused by: java.lang.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. "
        at android.support.v7.app.AppCompatDelegateImplV9.setSupportActionBar(AppCompatDelegateImplV9.java:204)
        at android.support.v7.app.AppCompatActivity.setSupportActionBar(AppCompatActivity.java:129)
        at com.itsdf07.app.mvp.main.MainActivity.onCreate(MainActivity.java:26)
        at android.app.Activity.performCreate(Activity.java:7372)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302) 
        at android.app.ActivityThread.-wrap12(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891) 
        at android.os.Handler.dispatchMessage(Handler.java:108) 
        at android.os.Looper.loop(Looper.java:166) 
        at android.app.ActivityThread.main(ActivityThread.java:7425) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921) 

什麼原因呢?啓動MainActivity界面失敗,原因是
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.

這個Activity(也就是要啓動的MainActivity)已經由 window decor提供了一個action bar,不需要重複請求 window的FEATURE_SUPPORT_ACTION_BAR,並且可以通過設置主題中的windowActionBar屬性爲false來代替它

爲什麼會這樣呢?程序不能只看表面,既然異常提到了theme,那麼我們就需要進一步往parent主題來定位原因,總能發現原因的

    <style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light">
        <item name="windowNoTitle">false</item>
        "<item name="windowActionBar">true</item>"
        <item name="windowActionBarOverlay">false</item>
        <item name="windowActionModeOverlay">false</item>
        <item name="actionBarPopupTheme">@null</item>
		......
    </style>

當看到上面的設置時,我們發現了<item name="windowActionBar">true</item>,也就是說當前所使用的主題其實是帶了一個ActionBar的,這麼一來,就好理解了,在已有ActionBar的基礎上在添加一個ActionBar,出現衝突了,能排查出原因的問題,那就都不是問題。因爲下面這個主題,就可以解決這個衝突

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

沒帶ActionBar的主題,我們想怎麼添加新的ActionBar都可以!
當然,如果想要全局都使用自定義ActionBar,那麼就直接在AndroidManifest.xmlapplication下的theme設置爲無ActionBar即可,如android:theme="@style/AppTheme.NoActionBar",如果只是針對某個視圖UI,那麼 就針對那個Activity進行設置即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章