我们在使用自定义标题栏时,一般的写法基本上是下面几步
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