Android: Appcompat 21如何在操作栏上添加阴影

20

我从新的appcompat中添加了新的Material Design ActionBar并使用了新的Toolbar小部件。我在xml上设置了自定义背景,但我的问题是Actionbar的下拉阴影没有显示。你知道该怎么做吗?

工具栏代码

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/my_awesome_toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@drawable/ab_background_textured"
    app:theme="@style/MyTheme"
    app:popupTheme="@style/MyTheme.Popup"/>

我的主题样式

<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textColorPrimary">@color/abc_primary_text_material_dark</item>
    <item name="actionMenuTextColor">@color/abc_primary_text_material_dark</item>
    <item name="android:textColorSecondary">#ffff8800</item>
</style>

MyTheme.Popup样式

<style name="MyTheme.Popup" parent="ThemeOverlay.AppCompat.Dark">
    <item name="android:textColor">#ffffff</item>
</style>

更新

像@Justin Powell建议的那样,我在我的主题上添加了actionBarStyle,但是仍然没有下拉阴影。

我的主题样式(已更新)

<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textColorPrimary">@color/abc_primary_text_material_dark</item>
    <item name="actionMenuTextColor">@color/abc_primary_text_material_dark</item>
    <item name="android:textColorSecondary">#ffff8800</item>
    <item name="android:actionBarStyle">@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse</item>
</style>

4个回答

34

我发现 Google IO 应用程序中的解决方案对我来说是可接受的,但没有博客或 Stackoverflow 帖子能够完全解释清楚。您可以做的是从 https://github.com/google/iosched/blob/36d88985ff6813fa9035530cd426393720a6f7b4/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png 获取他们的 Apache 2 许可的抽屉阴影资产,然后在您的 Activity 的布局中:

<RelativeLayout android:layout_width="match_parent"
                android:layout_height="match_parent">
    <include android:id="@+id/toolbar"
             layout="@layout/toolbar"/>

    <FrameLayout android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_below="@id/toolbar"
                 android:foreground="@drawable/header_shadow">
    <!-- YOUR STUFF HERE -->
    </FrameLayout>
</RelativeLayout>

然而标题阴影是什么。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="header_shadow" type="drawable">@drawable/bottom_shadow</item>
</resources>
对于API级别<21的情况,请参考https://github.com/google/iosched/blob/8c798c58e592b8a25111610e216c7f3ee74c3a42/android/src/main/res/values/refs.xmlhttps://github.com/google/iosched/blob/8c798c58e592b8a25111610e216c7f3ee74c3a42/android/src/main/res/values-v21/refs.xml
这是toolbar.xml的详细说明。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:elevation="4dp"
        app:theme="@style/ToolbarTheme"
        app:popupTheme="@style/AppTheme"/>

4
哦,这太美妙可怕了,但似乎是一个合理的方法。我会尝试一下。谢谢! - benhylau
在Lollipop及以上版本中,你会不会有两个阴影? - Kurovsky
不,你不会得到两个阴影,因为对于21及以上的版本,header_shadow是空的。请参见values-v21中的refs.xml文件。 - Fabian Frank
@FabianFrank 为什么你要使用 FrameLayout 来实现阴影效果,我们不能只使用普通的 View 类吗? - shakil.k
对我没起作用。阴影应用于整个布局,从顶部到底部屏幕。太糟糕了。与谷歌支持库一样糟糕。 - Trancer
显示剩余2条评论

30

对于5.0之前的布局,你可以通过在内容的FrameLayout中添加foreground="?android:windowContentOverlay"来将阴影添加回工具栏下面的内容。

例如:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

<FrameLayout
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="?android:windowContentOverlay"
    />

</LinearLayout>

5
这是他们在另一个活动布局中使用的可绘制对象:https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png 作为前景。 - Cassio Landim
GMail似乎在主窗口上使用了一个渐变形状。因此,他们使用FrameLayout先放置内容,然后再放置阴影。虽然很难找到渐变的正确值,但它确实起作用。您必须在API级别>= 21时隐藏阴影。 - Christer Nordvik
@tomrozb 完成了!希望它对你有用,或者其他人可以帮助改进它 :-) - Christer Nordvik
2
谷歌实现投影阴影的源代码:https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/DrawShadowFrameLayout.java - Ashish Rawat
@Ashish Rawat 我该如何使用这个Google源代码? - Itiel Maimon
显示剩余4条评论

12
这是我展示阴影的方式:
<!-- API level 21 and above then the elevation attribute is enough. For some reason it can't be set directly on the include so I wrap it in a FrameLayout -->
<FrameLayout
    android:id="@+id/topwrapper"
    android:background="@color/theme_primary"
    android:elevation="4dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <include layout="@layout/toolbar_actionbar" />
</FrameLayout>

<FrameLayout
    android:layout_below="@id/topwrapper"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- This topshadow is hidden in code for API level 21 and above -->
    <include layout="@layout/topshadow" />
</FrameLayout>

然后 topshadow 布局看起来像这样(调整 5dp 可以得到你想要的阴影高度):

<View xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:id="@+id/shadow_prelollipop"
    android:background="@drawable/background_shadow" />

background_shadow.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:startColor="#02444444"
        android:endColor="#33111111"
        android:angle="90"></gradient>
</shape>

toolbar_actionbar.xml

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myapp="http://schemas.android.com/apk/res-auto"
    myapp:theme="@style/ActionBarThemeOverlay"
    myapp:popupTheme="@style/ActionBarPopupThemeOverlay"
    android:id="@+id/toolbar_actionbar"
    android:background="@color/theme_primary"
    myapp:titleTextAppearance="@style/ActionBar.TitleText"
    myapp:contentInsetStart="?actionBarInsetStart"
    android:layout_width="match_parent"
    android:layout_height="?actionBarSize" />

0

actionbar_background.xml

    <item>
        <shape>
            <solid android:color="@color/black" />
            <corners android:radius="2dp" />
            <gradient
                android:startColor="@color/black"
                android:centerColor="@color/black"
                android:endColor="@color/white"
                android:angle="270" />
        </shape>
    </item>

    <item android:bottom="3dp" >
        <shape>

            <solid android:color="#ffffff" />
            <corners android:radius="1dp" />
        </shape>
    </item>
</layer-list>

将背景添加到操作栏样式

<style name="Theme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
    <item name="background">@drawable/actionbar_background</item>
    <item name="android:elevation">0dp</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:layout_marginBottom">5dp</item>
    <item name="logo">@drawable/ab_logo</item>
    <item name="displayOptions">useLogo|showHome|showTitle|showCustom</item>
</style>

添加到基础主题

  <style name="BaseTheme" parent="Theme.AppCompat.Light">
            <item name="android:homeAsUpIndicator">@drawable/home_back</item>
            <item name="actionBarStyle">@style/TFKBTheme.ActionBar</item>
    </style>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接