Android自定义标题栏异常You cannot combine custom titles with other title features

来源:互联网 发布:网络歌曲谢谢你陪着我 编辑:程序博客网 时间:2024/05/29 12:32

我们在使用自定义标题栏时,一般的写法基本上是下面几步

requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.activity_test_custom_title);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.common_titlebar);

有时候会出现如下异常

android.util.AndroidRuntimeException: You cannot combine custom titles with other title features

具体错误原因

Caused by: android.util.AndroidRuntimeException: You cannot combine custom titles with other title features
                                                                        at com.android.internal.policy.PhoneWindow.requestFeature(PhoneWindow.java:325)
                                                                        at com.android.internal.policy.PhoneWindow.generateLayout(PhoneWindow.java:3674)
                                                                        at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:3981)
                                                                        at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:383)
                                                                        at android.app.Activity.setContentView(Activity.java:2166)

网上常有一些解答,都是比较模糊的,比如替换Theme等等,至于为什么如此做,没有详细说明。

于是我准备从PhoneWindow这个类的源码(android4.4,完整路径\frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java)一探究竟。

首先我们从错误描述找到requestFeature方法,源码如下

public boolean requestFeature(int featureId) {
        if (mContentParent != null) {
            throw new AndroidRuntimeException("requestFeature() must be called before adding content");
        }
        final int features = getFeatures();
        if ((features != DEFAULT_FEATURES) && (featureId == FEATURE_CUSTOM_TITLE)) {

            /* Another feature is enabled and the user is trying to enable the custom title feature */
            throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
        }
        if (((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) &&
                (featureId != FEATURE_CUSTOM_TITLE) && (featureId != FEATURE_ACTION_MODE_OVERLAY)) {


            /* Custom title feature is enabled and the user is trying to enable another feature */
            throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
        }
        if ((features & (1 << FEATURE_NO_TITLE)) != 0 && featureId == FEATURE_ACTION_BAR) {
            return false; // Ignore. No title dominates.
        }
        if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_NO_TITLE) {
            // Remove the action bar feature if we have no title. No title dominates.
            removeFeature(FEATURE_ACTION_BAR);
        }
        return super.requestFeature(featureId);
    }

从方法实现我们看到有两个地方会抛出这个异常。第一个if:FEATURE_CUSTOM_TITLE必须是第一个设置的,否则抛出异常。第二个if:当已经设置了FEATURE_CUSTOM_TITLE,只能再次设置FEATURE_CUSTOM_TITLE或者FEATURE_ACTION_MODE_OVERLAY,否则抛出异常。(当然设置FEATURE_CUSTOM_TITLE必须要在setContentView之前)

好了,了解了抛出异常的条件,我们定位到前一个调用的方法generateLayout,关键部分如下

if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        } else if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionBar, false)) {
            // Don't allow an action bar if there is no title.
            requestFeature(FEATURE_ACTION_BAR);
        }

        if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionBarOverlay, false)) {
            requestFeature(FEATURE_ACTION_BAR_OVERLAY);
        }

        if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionModeOverlay, false)) {
            requestFeature(FEATURE_ACTION_MODE_OVERLAY);
        }

这里有4个设置feature的地方,我们知道如果设置了FEATURE_CUSTOM_TITLE,只允许设置FEATURE_CUSTOM_TITLE或FEATURE_ACTION_MODE_OVERLAY

因此,我们只需要自定义一个主题,然后将上面前三项都设为false即可,如下

<style name="CustomTitleTheme" parent="AppTheme">    <item name="android:windowNoTitle">false</item>    <item name="android:windowActionBar">false</item>    <item name="android:windowActionBarOverlay">false</item></style>

如此,问题解决。

End




0 0
原创粉丝点击