您的位置:首页 > 移动开发 > Android开发

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

2016-06-03 10:30 435 查看
我们在使用自定义标题栏时,一般的写法基本上是下面几步

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息