日常开发中偶尔遇到需要修改标题栏样式的情况,这个时候就需要用到requestWindowFeature(int featureId)来设置窗口样式。
featureId有如下几种值:
- DEFAULT_FEATURES:系统默认状态,一般不需要指定
- FEATURE_CONTEXT_MENU:启用ContextMenu,默认该项已启用,一般无需指定
- FEATURE_CUSTOM_TITLE:自定义标题。当需要自定义标题时必须指定。如:标题是一个按钮时
- FEATURE_INDETERMINATE_PROGRESS:不确定的进度
- FEATURE_LEFT_ICON:标题栏左侧的图标
- FEATURE_NO_TITLE:无标题
- FEATURE_OPTIONS_PANEL:启用“选项面板”功能,默认已启用。
- FEATURE_PROGRESS:进度指示器功能
- FEATURE_RIGHT_ICON:标题栏右侧的图标
各自的样式大家可以自己尝试一下,我们这次只是探讨为什么requestWindowFeature方法要在setContentView()方法之前调用。
要理解为什么requestWindowFeature()方法要在setContentView()方法之前调用,我们首先要看一下Android的窗口的UI架构。
如图所示,每个Activity中都包含一个Window类的对象,一般这个Window类的对象是由PhoneWindow实现的,也就是Avtivity内部有一个PhoneWindow的对象。而这个PhoneWindow对象会将一个DecorView对象设置成整个窗口的根View。这样看来也就说,整个Activity显示的是一个DecorView。而在DecorView内部将显示内容分为TitleView和ContentView两个部分。ContentView大家都比较熟悉,它是一个ID为content的FrameLayout,我们通过setContentView()设置的布局就会被添加到这个FrameLayout上。
DecorView中的布局关系如上图,我们看一下setContentView方法的代码。
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
首先它会设置FrameLayout的布局,之后回初始化ActionBar。看到这里我们就明白了,如果在setContentView方法之后设置requestWindowFeature()方法的话,由于已经初始化了ActionBar,所以并不会引起UI显示上的变化,必须在setContentView之前调用requestWindowFeature()方法才能在ActionBar初始化的时候影响它的显示。