【问题标题】:Remove action bar shadow programmatically以编程方式删除操作栏阴影
【发布时间】:2013-11-24 04:23:26
【问题描述】:

如何从 java 代码中删除操作栏的阴影?.

如果我从样式中删除它工作正常。

<style name="MyTheme" parent="Theme.Sherlock">
....
<item name="windowContentOverlay">@null</item>
<item name="android:windowContentOverlay">@null</item>
....
</style>

但我需要从 java 代码中动态删除和添加它。

【问题讨论】:

  • 我能问你为什么要使用 java 删除它吗?
  • 我想要阴影,在某些活动而不是其他活动的操作栏下方。

标签: android styles android-actionbar android-theme dropshadow


【解决方案1】:

无法以编程方式设置windowContentOverlay 属性的值。但是您可以定义两种不同的主题,一种用于带有可见 ActionBar 阴影的活动,另一种用于其他主题:

<!-- Your main theme with ActionBar shadow. -->
<style name="MyTheme" parent="Theme.Sherlock">
    ....
</style>

<!-- Theme without ActionBar shadow (inherits main theme) -->
<style name="MyNoActionBarShadowTheme" parent="MyTheme">
    <item name="windowContentOverlay">@null</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

现在您可以将它们设置为AndroidManifest.xml中的活动:

<!-- Activity with ActionBar shadow -->
<activity
    android:name=".ShadowActivity"
    android:theme="@style/MyTheme"/>

<!-- Activity without ActionBar shadow -->
<activity
    android:name=".NoShadowActivity"
    android:theme="@style/MyNoActionBarShadowTheme"/>

或者您可以在onCreate() 方法中以编程方式设置正确的主题:

@Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.MyNoActionBarShadowTheme);
    super.onCreate(savedInstanceState);

    //...
}

【讨论】:

    【解决方案2】:

    如果你不会制作更多主题,那么试试这个。这对我很有效!

    public void disableActionbarShadow() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            View v = getActivity().findViewById(android.R.id.content);
            if (v instanceof FrameLayout) {
                ((FrameLayout) v).setForeground(null);
            }
        }else {
            // kitkat.
            // v is ActionBarOverlayLayout. unfortunately this is internal class.
            // if u want to check v is desired class, try this
            //   if(v.getClass().getSimpleName.equals("ActionBarOverlayLayout")) 
            // (we cant use instanceof caz ActionBarOverlayLayout is internal package)
            View v = ((ViewGroup)getActivity().getWindow().getDecorView()).getChildAt(0);
            v.setWillNotDraw(true);
        }
    }
    

    从 Kitkat(也许)开始,ActionBarOverlayLayout 包含在活动的视图树中。
    这显示了操作栏阴影(我认为 XD)

    参考:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/com/android/internal/widget/ActionBarOverlayLayout.java#79

    Becaraful 我不知道如果使用支持库版本会发生什么。

    【讨论】:

      【解决方案3】:

      我知道这个问题很老,但这个问题对我来说是新问题,所以它也可能对其他人有帮助。

      试试:

      • getSupportActionBar().setElevation(0);

      或者,如果您没有使用自定义操作栏:

      • getActionBar().setElevation(0);

      我认为这是以编程方式执行此操作的最简单方法。

      【讨论】:

        【解决方案4】:

        像这样定义一个新样式。请注意,没有定义父级:

        <style name="ConOver" >    <<== no parent
            <item name="android:windowContentOverlay">@null</item>
        </style>
        

        在代码上方添加:

        // Add this line before setContentView() call
        // Lets you add new attribute values into the current theme
        getTheme().applyStyle(R.style.ConOver, true);
        
        // Rest stays the same
        

        【讨论】:

        • 我不知道为什么这个答案被否决了,这是以编程方式删除操作栏阴影的方法,并且有效。
        • 可能是因为它只在 setContentView 之前有效,这违背了以编程方式执行它的目的。最好在活动开始时有不同的风格。
        • @GregEnnis 嗨,格雷格,我不知道你为什么考虑让两个活动它们使用的样式不同“更好”。此外,如果您注意到,我们正在向/在样式中添加/更新一个属性——而不是使用不同的属性。您能否指出此页面上不推荐的一个答案 - 使用两个单独的活动 ||重新创建活动 ||设置主题 before setContentView(...) .
        • @GregEnnis 顺便说一句,接受的答案的(第二部分)与我的限制相同,发布时间比我的要晚得多,并且建议使用两个单独的主题而不是在运行时覆盖属性。在发帖时,我在 SO 上激怒了某人,他们连续对我的答案投了反对票。在发布的瞬间,我获得了-2。没有人愿意用这个分数来尝试答案:))。
        • @Vikram 好吧,我并没有对你投反对票,实际上我只是投了你一票,因为 getTheme().applyStyle() 是一个很好的工具,可以放在花招中。它当然在其他情况下也很有用。仅仅改变一种风格的观点不需要完全不同的主题定义。
        【解决方案5】:

        声明 2 种样式 ne 有阴影,而另一种没有。然后在您的清单中用各自的主题定义每个活动的主题。 例如

        <Activity 
        android:theme="@style/ThemeShadow" ...>
        
        ...
        
        <Activity 
        android:theme="@style/ThemeNoShadow" ...>
        

        【讨论】:

          【解决方案6】:

          我找到了这篇文章: Change Theme of Layout Runtime by Button Click in Android

          它允许您更改活动的主题,但它确实调用完成()并重新启动活动。所以,我不确定它是否能满足您的需求。

          import android.app.Activity;
          import android.content.Intent;
          
          public class Utils
          {
               private static int sTheme;
          
               public final static int THEME_DEFAULT = 0;
               public final static int THEME_WHITE = 1;
               public final static int THEME_BLUE = 2;
          
                /**
                 * Set the theme of the Activity, and restart it by creating a new Activity of the same type.
                 */
                public static void changeToTheme(Activity activity, int theme)
                {
                     sTheme = theme;
                     activity.finish();
          
           activity.startActivity(new Intent(activity, activity.getClass()));
          
                }
          
                /** Set the theme of the activity, according to the configuration. */
                public static void onActivityCreateSetTheme(Activity activity)
                {
                     switch (sTheme)
                          {
                          default:
                     case THEME_DEFAULT:
                         activity.setTheme(R.style.FirstTheme);
                         break;
                     case THEME_WHITE:
                         activity.setTheme(R.style.SecondTheme);
                         break;
                     case THEME_BLUE:
                         activity.setTheme(R.style.Thirdheme);
                         break;
                     }
                }
           }
          

          【讨论】:

            【解决方案7】:

            如果supportActionBar.elevation=0f 不适合你, 您可以通过设置appBar.targetElevation=0f 来移除阴影,但此方法已弃用。 新方法是使用StateListAnimator

            您必须将stateListAnimator 设置为AppBarLayout 而无需通过以下步骤实现的提升

            1. 创建动画资源appbar_animator.xml

              <item
                  android:state_enabled="true"
                  app:state_collapsed="false"
                  app:state_collapsible="true">
                  <objectAnimator
                      android:duration="150"
                      android:propertyName="elevation"
                      android:valueTo="0dp"
                      android:valueType="floatType" />
              </item>
              
              <item android:state_enabled="true">
                  <objectAnimator
                      android:duration="150"
                      android:propertyName="elevation"
                      android:valueTo="0dp"
                      android:valueType="floatType" />
              </item>
              
              <item>
                  <objectAnimator
                      android:duration="0"
                      android:propertyName="elevation"
                      android:valueTo="0"
                      android:valueType="floatType" />
              </item>
              

              android.valueTo="0dp" 定义海拔。

            2. 膨胀并将StateListAnimator设置为appBar

              val stateAnimator=AnimatorInflater.loadStateListAnimator(this,R.animator.appbar_animator);
              appBar.stateListAnimator=stateAnimator
              

            StateListAnimator 已添加到 api 21 Lollipop

            【讨论】:

              猜你喜欢
              • 2012-08-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-10-08
              • 2016-01-29
              相关资源
              最近更新 更多