web-dev-qa-db-ja.com

すべてのAndroidバージョンでサポートライブラリのActionBar&Toolbarの影を表示する方法は?

これは簡単な質問です:

新しいサポートライブラリを使用します。これにより、Toolbarインスタンスを作成し、それをアクティビティのactionBarとして設定することもできます(またはデフォルトのインスタンスを使用します)。

ツールバー(またはデフォルトのActionBar)によってキャストされるシャドウをカスタマイズするにはどうすればよいですか?

「setElevation」を(両方とも)使用しようとしましたが、Android Lollipop。

また、Lollipopより前のバージョンの影をカスタマイズする方法が見つかりません。このためのAPIはありますか?または少なくともドローアブル(私は試しましたが、見つかりませんでした)?


はい、次のことを見つけることができました。

Lollipopとpre-Lollipopの両方で、アクティビティが通常のAppCompatテーマ(「Theme.AppCompat.Light」など)を使用する場合、影はよく見えるはずです。

ただし、「setSupportActionBar」を使用する場合(および「Theme.AppCompat.Light.NoActionBar」などの適切なテーマを使用する場合)、シャドウにいくつかの問題が発生します。

Lollipop以前の場合は、ツールバーの下にFrameLayoutを配置できます。これは、通常のテーマで使用されているものとまったく同じように見えます。

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    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:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/toolbar"
        Android:foreground="?android:windowContentOverlay"
        Android:visibility="@integer/action_bar_shadow_background_visibility" />

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/toolbar"
        Android:text="@string/hello_world" />

</RelativeLayout>

FrameLayoutをアクティビティのコンテンツとして使用することも、私が行ったことを使用することもできます。 「action_bar_shadow_background_visibility」で行ったように、Lollipopより前の場合は整数0を、Lollipop以上の場合は2を設定することにより、可視性を設定することもできます。

これは醜い解決策ですが、機能しますが、Lollipopより前のバージョンでのみ機能します。

いずれにしても、「setSupportActionBar」を使用した場合、Lollipopの影をうまく表示する方法を見つけることができませんでした。ツールバーとアクションバーで「setElevation」を使用してみました(「setSupportActionBar」を呼び出した直後に「getSupportActionBar」を使用)。

多くのチュートリアルがツールバーに「minHeight」を使用するように言っていることに気付いたので、アクションバーの標準の高さを取得する方法も取得しません。これについても助けていただければ幸いです。

誰かがこれを手伝ってくれる?

繰り返しますが、明確にするために、これは私が尋ねるものです:

  • プレロリポップの場合、ツールバーとアクションバーの両方のサポートライブラリで使用されているものと同じ影を表示します。
  • Lollipopにも同じ(ただし、Lollipopにあるものを使用)
  • 追加:シャドウをLollipopでより「繊細」にカスタマイズします(おそらくすべてのバージョンでカスタマイズします)。
  • 追加:ツールバーのminHeightが、高さ自体ではなく、アクションバーの高さの値を取得するのはなぜですか?

編集:OK、これは私がLollipopの影を模倣するためにこれまでに行った限りです:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    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" />

    <include
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/toolbar"
        layout="@layout/toolbar_action_bar_shadow" />

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/toolbar"
        Android:text="@string/hello_world" />

</RelativeLayout>

res/layout/toolbar_action_bar_shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:foreground="?android:windowContentOverlay" />

res/layout-v21/toolbar_action_bar_shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:src="@drawable/msl__action_bar_shadow" />

res/drawable-v21/res/layout/msl__action_bar_shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android" >

    <!-- intended for Lollipop and above -->

    <item>
        <shape
            Android:dither="true"
            Android:shape="rectangle" >
            <gradient
                Android:angle="270"
                Android:endColor="#00000000"
                Android:startColor="#33000000" />

            <size Android:height="10dp" />
        </shape>
    </item>

</layer-list>

まったく同じではありませんが、似ています。


編集:なぜそれが起こるのかまだわかりません。私が質問に書いたコードは誤解を招くものだと思います。背景を設定するだけです。それでも、私がテストしているアプリでは、まだ役に立ちません。私が修正しようとしているアプリには、ナビゲーションドロワーの上にツールバーがあります。

(ツールバーから拡張された)カスタマイズされたツールバーを作成し、(ナビゲーションドロワーに従って)アルファ値を変更したことが原因であると考えましたが、通常のツールバーを使用して、関連するすべてのものを無効にしてもアルファに、それはまだ機能しません。また、それだけでなく、まったく新しいプロジェクトで、ツールバーに半透明の背景を設定しようとしましたが、 "setElevation"メソッドに従って影が付けられました。

今では、この問題の原因を見つけるのはさらに困難です。なぜなら、それは透明性のためではなく、カスタムツールバークラスのためではないようです...

これが何らかの方法で役立つ場合に備えて、ツールバーのあるアクティビティのレイアウトを次に示します。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <Android.support.v4.widget.DrawerLayout
        Android:id="@+id/activity_main__drawerLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" >

        <FrameLayout
            Android:id="@+id/activity_main__fragmentContainer"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />

        <include
            Android:layout_width="240dp"
            Android:layout_height="match_parent"
            Android:layout_gravity="left"
            Android:layout_marginTop="?attr/actionBarSize"
            layout="@layout/activity_main__sliding_menu" />
    </Android.support.v4.widget.DrawerLayout>

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical" >

        <com.app.ui.Toolbar
            Android:id="@+id/activity_main__toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:background="?attr/colorPrimary"
            Android:layoutDirection="ltr"
            Android:minHeight="?attr/actionBarSize"
            app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
            tools:ignore="UnusedAttribute" />

        <!-- <include -->
        <!-- Android:layout_width="match_parent" -->
        <!-- Android:layout_height="wrap_content" -->
        <!-- layout="@layout/toolbar_action_bar_shadow" /> -->
    </LinearLayout>

</FrameLayout>
15

私の知る限り、または読める範囲では、AppCompatライブラリは現在影を描画しません。呼び出しは存在するようです(例:ViewCompat.setElevation(View view, float elevation))。ただし、何も実行していないようです。

したがって、少なくともサポートライブラリがシャドウレンダリングを実装するまでは、今のところ独自のシャドウを追加することに頼る必要があると思います。

Google IO 2014のソースコードを見ると、次のように実装されています。

  • DrawShadowFrameLayout これは、背景のドローアブルを影としてレンダリングできます
  • bottom_shadow.9.png アクションバーの下の影を表します
  • app:shadowDrawable シャドウドローアブルを設定する属性
  • drawShadowFrameLayoutのsetShadowTopOffset()は、影を下にシフトして、アクションバーの下にうまく表示されるようにします。 (これを自分で設定する必要があります)

この詳細情報 Reddit Thread および stackoverflow

14
Jeroen Mols

これは私が私のアプリの1つで行ったものであり、影(人工的な影)を示しています。

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/mainActivityLinearLayout"
        Android:layout_width="match_parent"
        Android:orientation="vertical"
        Android:layout_height="match_parent"
        Android:background="@drawable/logo">

      <LinearLayout
        Android:layout_height="?attr/actionBarSize"
        Android:layout_width="match_parent"
        Android:orientation="vertical">

        <!-- refer to your toolbar layout -->
        <include layout="@layout/toolbar"/>

      </LinearLayout>

      <!-- My Left Drawer -->
      <Android.support.v4.widget.DrawerLayout
        Android:id="@+id/drawer_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"    >

        <RelativeLayout
            xmlns:Android="http://schemas.Android.com/apk/res/Android"
            Android:id="@+id/relative_layout"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:layout_marginStart="0dp"
            Android:layout_marginLeft="0dp" >

           ....

           <!-- Lots of other stuffs -->             

           ....

           <!-- Shadow -->
          <View
           Android:layout_width="match_parent"
           Android:layout_below="@+id/toolbarShadow"
           Android:layout_marginTop="0dp"
           Android:layout_height="6dp"
           Android:background="@drawable/toolbar_dropshadow" />

        </RelativeLayout>
     </Android.support.v4.widget.DrawerLayout>


 </LinearLayout>

toolbar_dropshadow.xml:

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
    <shape>
        <gradient
            Android:angle="90"
            Android:startColor="@Android:color/transparent"
            Android:endColor="#D6D6D6"
            Android:type="linear" />
    </shape>
</item>
</selector>

私はマップアクティビティを使用していますが、これはすべてマップビューに素晴らしい影を表示しています。

お役に立てれば...

3
Abhinav Puri