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进行设置即可

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