ActionBarCompat:在创建活动之前隐藏ActionBar(bug?)

もっく*_*っくん 16 android android-actionbar android-actionbar-compat

所以我使用ActionBarSherlock并决定切换到新的ActionBarCompat.使用ABS,可以使用本文中描述的方式隐藏ActionBar: 如何在创建活动之前隐藏操作栏,然后再次显示它?

但是,随着ActionBarCompat上API14的应用程序崩溃,因为当你设置android:windowActionBarfalsegetSupportActionBar()方法返回null,即使你已经宣布getWindow().requestFeature(Window.FEATURE_ACTION_BAR);进入onCreate()方法.

有趣的是,如果你打电话getActionBar(),你得到的对象,一切正常.

那么,这是一个错误还是我错过了什么?欢迎任何想法!


styles.xml 文件:

<style name="Theme.MyApp" parent="@style/Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowActionBar">false</item>
    <item name="android:windowTitleSize">0dp</item>
</style>
Run Code Online (Sandbox Code Playgroud)

MyActivity.java 文件:

...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get the action bar feature. This feature is disabled by default into the theme
    // for specific reasons.
    getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
    ...
    // By default the action bar is hidden.
    getSupportActionBar().hide();
}
Run Code Online (Sandbox Code Playgroud)

st_*_*st_ 19

我遇到了同样的问题,在我看来,发现了这种奇怪行为的原因.我查看了支持库的来源,得到了这个:

mHasActionBarActionBarActivityDelegate中创建新操作栏之前,Appcompat会检查变量值

final ActionBar getSupportActionBar() {
    // The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar
    // could change after onCreate
    if (mHasActionBar || mOverlayActionBar) {
        if (mActionBar == null) {
            mActionBar = createSupportActionBar();
    ...
Run Code Online (Sandbox Code Playgroud)

我们可以通过调用改变它的值supportRequestWindowFeature(int featureId)是通过委派ActionBarActivityActionBarActivityDelegate.

有基委托类ActionBarDelegateBase及其后代ActionBarDelegateHC,ActionBarActivityDelegateICS,ActionBarActivityJB,其中之一根据一个版本运行Android的选择.和方法supportRequestWindowFeature实际上是工作得很好,几乎在所有这些,但它覆盖在ActionBarActivityDelegateICS这样的

@Override
public boolean supportRequestWindowFeature(int featureId) {
    return mActivity.requestWindowFeature(featureId);
}
Run Code Online (Sandbox Code Playgroud)

所以它对变量没有影响mHasActionBar,这就是为什么getSupportActionBar()返回null.

我们快到了.我找到了两种不同的解决方案.

第一种方式

  1. git导入appcompat的源项目

  2. 将重写的方法更改ActionBarActivityDelegateICS.java为类似的方法

    @Override
    public boolean supportRequestWindowFeature(int featureId) {
        boolean result = mActivity.requestWindowFeature(featureId);
        if (result) {
            switch (featureId) {
            case WindowCompat.FEATURE_ACTION_BAR:
                mHasActionBar = true;
            case WindowCompat.FEATURE_ACTION_BAR_OVERLAY:
                mOverlayActionBar = true;
            }
        }
        return result;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将此行放在activity的onCreate方法之前getSupportActionBar()

    supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
    
    Run Code Online (Sandbox Code Playgroud)

第二种方式

  1. 从android SDK导入appcompat的项目(带有空的src目录)

  2. 将此方法添加到您的活动中

    private void requestFeature() {
        try {
            Field fieldImpl = ActionBarActivity.class.getDeclaredField("mImpl");
            fieldImpl.setAccessible(true);
            Object impl = fieldImpl.get(this);
    
            Class<?> cls = Class.forName("android.support.v7.app.ActionBarActivityDelegate");
    
            Field fieldHasActionBar = cls.getDeclaredField("mHasActionBar");
            fieldHasActionBar.setAccessible(true);
            fieldHasActionBar.setBoolean(impl, true);
    
        } catch (NoSuchFieldException e) {
            Log.e(LOG_TAG, e.getLocalizedMessage(), e);
        } catch (IllegalAccessException e) {
            Log.e(LOG_TAG, e.getLocalizedMessage(), e);
        } catch (IllegalArgumentException e) {
            Log.e(LOG_TAG, e.getLocalizedMessage(), e);
        } catch (ClassNotFoundException e) {
            Log.e(LOG_TAG, e.getLocalizedMessage(), e);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 调用requestFeature()onCreate你的活动这样的方法

    if (Build.VERSION.SDK_INT >= 11) {
        requestFeature();
    }
    supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
    
    Run Code Online (Sandbox Code Playgroud)

我用第二种方式.就这样.


Mik*_*ike 5

我用这个来隐藏AppCompat:style.xml中的ActionBar

<style name="Theme.AppCompat.Light.NoActionBar" parent="@style/Theme.AppCompat.Light">
    <item name="android:windowNoTitle">true</item>
</style>
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml中:

<activity
        android:name=".Splash"
        android:label="@string/title_activity_splash"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)