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

时间:2013-08-30 06:11:54

标签: android android-actionbar android-actionbar-compat

所以我使用ActionBarSherlock并决定切换到新的ActionBarCompat。使用ABS,可以使用本文中描述的方式隐藏ActionBar: How to hide action bar before activity is created, and then show it again?

但是,使用ActionBarCompat,应用程序在API14上崩溃,因为当您将android:windowActionBar设置为false时,getSupportActionBar()方法返回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>

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();
}

4 个答案:

答案 0 :(得分:19)

我遇到了同样的问题,在我看来,发现了这种奇怪行为的原因。我浏览了support library的来源并得到了这个:

ActionBarActivityDelegate

中创建新操作栏之前,Appcompat会检查mHasActionBar变量的值
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();
    ...

我们可以通过调用由supportRequestWindowFeature(int featureId)委派给ActionBarActivityDelegateActionBarActivity来更改其价值。

有基础委托类ActionBarDelegateBase及其后代ActionBarDelegateHCActionBarActivityDelegateICSActionBarActivityJB,其中一个是根据运行的android版本选择的。方法supportRequestWindowFeature实际上几乎可以在所有方法中正常工作,但它在ActionBarActivityDelegateICS中被覆盖了

@Override
public boolean supportRequestWindowFeature(int featureId) {
    return mActivity.requestWindowFeature(featureId);
}

因此它对变量mHasActionBar没有影响,这就是getSupportActionBar()返回null的原因。

我们几乎在那里。我找到了两种不同的解决方案。

第一种方式

  1. git

  2. 导入appcompat的源项目
  3. 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;
    }
    
  4. onCreate

    之前将此行放在活动的getSupportActionBar()方法中
    supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
    
  5. 第二种方式

    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);
          }
      }
      
    3. 在此活动的requestFeature()方法中调用onCreate

      if (Build.VERSION.SDK_INT >= 11) {
          requestFeature();
      }
      supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
      
    4. 我用第二种方式。就是这样。

答案 1 :(得分:5)

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

<style name="Theme.AppCompat.Light.NoActionBar" parent="@style/Theme.AppCompat.Light">
    <item name="android:windowNoTitle">true</item>
</style>

的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>

答案 2 :(得分:0)

我不知道我是否完全明白你的问题,但我会去。

我认为您需要同时使用旧版本getSupportActionBar()和最新版本getActionBar()。这不是一个错误。

在使用这些方法之前,您需要验证设备版本。

我希望能够提供帮助。

答案 3 :(得分:0)

您的活动是否扩展了ActionBarActivity?可能它没有,这就是它使用getActionbar()方法运行的原因。