Android "Höhe" zeigt keinen Schatten

273

Ich habe eine ListView und möchte, dass mit jedem Listenelement ein Schatten darunter angezeigt wird. Ich verwende die neue Höhenfunktion von Android Lollipop, um ein Z für die Ansicht festzulegen, für die ich einen Schatten werfen möchte, und mache dies bereits effektiv mit der ActionBar (technisch eine Symbolleiste in Lollipop). Ich verwende die Höhe von Lollipop, aber aus irgendeinem Grund wird unter den Listenelementen kein Schatten angezeigt. So wird das Layout jedes Listenelements eingerichtet:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    >

    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_marginLeft="40dp"
        android:layout_marginRight="40dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:elevation="30dp"
        >

        <ImageView
            android:id="@+id/documentImageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop" />

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/alphared"
            android:layout_alignParentBottom="true" >

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="light"
                android:paddingLeft="16dp"
                android:paddingTop="8dp"
                android:paddingBottom="4dp"
                android:singleLine="true"
                android:text="New Document"
                android:textSize="27sp"/>

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentPageCount"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="italic"
                android:paddingLeft="16dp"
                android:layout_marginBottom="16dp"
                android:text="1 page"
                android:textSize="20sp"/>

        </LinearLayout>

    </RelativeLayout>

</RelativeLayout>

Hier ist jedoch, wie das Listenelement ohne Schatten angezeigt wird: Geben Sie hier die Bildbeschreibung ein

Ich habe auch Folgendes ohne Erfolg versucht:

  1. Stellen Sie die Höhe auf ImageView und TextViews selbst anstelle des übergeordneten Layouts ein.
  2. Hat einen Hintergrund auf die ImageView angewendet.
  3. Verwendete ÜbersetzungZ anstelle von Elevation.
AggieDev
quelle
Ich habe Ihr Layout (ohne benutzerdefinierte Ansichten) ausprobiert und den Schatten in meinem Telefon angezeigt. Können Sie ein minimales Projekt freigeben, das das Problem reproduziert?
rnrneverdies
1
Mögliches Duplikat von Android L FAB Button shadow
naveejr
Verwandte Frage: stackoverflow.com/questions/26572048/…
stefan222

Antworten:

383

Ich habe ein bisschen mit Schatten auf Lollipop herumgespielt und Folgendes gefunden:

  1. Es scheint, dass die ViewGroupGrenzen eines Elternteils aus irgendeinem Grund den Schatten seiner Kinder abschneiden; und
  2. Schatten, die mit gesetzt android:elevationsind, werden durch die ViewGrenzen des 's abgeschnitten, nicht durch die Grenzen, die sich durch den Rand erstrecken;
  3. Der richtige Weg, um eine untergeordnete Ansicht zum Anzeigen von Schatten zu erhalten, besteht darin, die Auffüllung für das übergeordnete Element und das übergeordnete Element android:clipToPadding="false"festzulegen.

Hier ist mein Vorschlag an Sie, basierend auf dem, was ich weiß:

  1. Stellen Sie Ihre oberste Ebene so ein RelativeLayout, dass die Auffüllung den Rändern entspricht, die Sie für das relative Layout festgelegt haben, für das Sie Schatten anzeigen möchten.
  2. eingestellt android:clipToPadding="false"auf derselben RelativeLayout;
  3. Entfernen Sie den Rand von dem Rand, für den RelativeLayoutauch die Höhe eingestellt ist.
  4. [BEARBEITEN] Möglicherweise müssen Sie auch eine nicht transparente Hintergrundfarbe für das untergeordnete Layout festlegen, das angehoben werden muss.

Am Ende des Tages sollte Ihr relatives Layout auf oberster Ebene folgendermaßen aussehen:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    android:paddingLeft="40dp"
    android:paddingRight="40dp"
    android:paddingTop="20dp"
    android:paddingBottom="20dp"
    android:clipToPadding="false"
    >

Das relative Innenlayout sollte folgendermaßen aussehen:

<RelativeLayout
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:background="[some non-transparent color]"
    android:elevation="30dp"
    >
Justin Pollard
quelle
8
Danke dafür! Ich fand auch android: clipChildren = "false" nützlich, wenn es auf das übergeordnete relative Layout angewendet wird.
Blaffie
1
Freut mich, @blaffie zu helfen!
Justin Pollard
214
Es ist so ärgerlich, dass Google so schlechten Code produziert. Wir müssen diese Framework-Fehler jahrelang berücksichtigen.
Miguel
8
Google sagt nur (leider): " Schatten werden vom übergeordneten Element der erhöhten Ansicht gezeichnet und unterliegen daher einem Standardansichtsausschnitt, der standardmäßig vom übergeordneten Element abgeschnitten wird. "
John
5
In meinem Fall war es die transparente Farbe. Ok, transparente Dinge werfen keine Schatten ... haha
Ferran Maylinch
285

Wenn Sie eine Ansicht ohne Hintergrund haben, hilft Ihnen diese Zeile

android:outlineProvider="bounds"

Standardmäßig wird der Schatten durch den Hintergrund der Ansicht bestimmt. Wenn also kein Hintergrund vorhanden ist, gibt es auch keinen Schatten.

Dmitry Ryadnenko
quelle
11
Was für eine seltsame Sache, Vorschau zeigte Höhe, aber echtes Gerät nicht. Danke, dieser hat das Problem behoben.
Ioane Sharvadze
Funktioniert für API Level 21 und höher
Pantelis Ieronimakis
10
Diese Art funktionierte für mich, gab aber einen diagonalen Rand an den Seiten, wenn sie auf eine Textansicht angewendet wurde. Das Einstellen des Hintergrunds auf eine Farbe (wie die Hintergrundfarbe der Eltern) funktionierte besser.
Gober
4
Dies gilt auch, wenn Ihr Hintergrund benutzerdefiniert ist und keine hat <solid>.
David Lord
Dies kann umgekehrt verwendet werden. Wenn Sie einen nicht transparenten Hintergrund mit Höhe und keinen Schatten wünschen. Einfach einstellen auf none. Vielen Dank!
Odys
101

Anscheinend können Sie nicht einfach eine Ansicht in einer Ansicht festlegen und anzeigen lassen. Sie müssen auch einen Hintergrund angeben.

Die folgenden Zeilen, die meinem LinearLayout hinzugefügt wurden, zeigten schließlich einen Schatten:

android:background="@android:color/white"
android:elevation="10dp"
John Slavick
quelle
Es war unerwartet. Ich habe ImageView mit src eingestellt und nach einer Lösung gesucht. Danke dir.
Andrew Grow
47

Eine andere Sache, die Sie beachten sollten: Schatten werden nicht angezeigt, wenn Sie diese Zeile im Manifest haben:

android: hardwareAccelerated = "false"

Ich habe alle vorgeschlagenen Dinge ausprobiert, aber es hat nur bei mir funktioniert, als ich die Zeile entfernt habe. Der Grund, warum ich die Zeile hatte, war, dass meine App mit einer Reihe von Bitmap-Bildern funktioniert und die App abstürzt.

nada
quelle
1
Dies löst das Problem nicht, wenn Sie dieses Flag benötigen, um vorhanden zu sein.
Clive Jefferies
Danke!! Ich verbrachte einen Tag damit, die AppBar zu erhöhen, und fand das Problem, als ich das Manifest auf dieses Aktivitätsflag überprüfte
ir2pid
1
Ich habe alle möglichen Lösungen ausprobiert, aber keine Arbeit für mich. Diese Lösungen haben funktioniert. Vielen Dank. Auch android:clipToPadding="false"mit dieser Lösung brauchen .
Chirag Savsani
29

Wenn Sie eine Ansicht ohne Hintergrund haben, hilft Ihnen diese Zeile

android:outlineProvider="bounds"

Wenn Sie eine Ansicht mit Hintergrund haben, hilft Ihnen diese Zeile

android:outlineProvider="paddedBounds"
Deepak Sharma
quelle
6
Diese Lösung ist die einzige, die für mich funktioniert. Vielen Dank
Oleh Liskovych
4
Dies funktioniert nur, wenn Sie einen Radius im Hintergrund Ihrer Ansicht haben. In diesem Fall wird der Schatten als rechteckig angezeigt, paddedBounds funktioniert jedoch für eine Ansicht mit Hintergrund.
Trevor Hart
android:outlineProvider="paddedBounds"Diese Linie hat bei mir funktioniert. Ich habe Selector Drawable eingestellt.
Chirag Savsani
1
Wenn ich dies verwendet habe, wird der Schatten vollständig innerhalb der Ansicht und nicht außerhalb gezeichnet, was ich nicht möchte.
AndroidGy
12

Ugh, ich habe gerade eine Stunde damit verbracht, das herauszufinden. In meinem Fall hatte ich einen Hintergrund eingestellt, der jedoch auf eine Farbe eingestellt war. Dies reicht nicht aus. Sie müssen den Hintergrund der Ansicht auf ein Zeichenelement setzen.

zB Dies wird keinen Schatten haben:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@color/ight_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

aber das wird

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@drawable/selector_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

BEARBEITEN: Haben Sie auch festgestellt, dass, wenn Sie einen Selektor als Hintergrund verwenden und die Ecke nicht eingestellt ist, der Schatten nicht im Vorschaufenster angezeigt wird, sondern auf dem Gerät

zB Dies hat keinen Schatten in der Vorschau:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>

aber das tut:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <corners android:radius="1dp" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>
Odiggität
quelle
1
Das genaue Gegenteil von Ihrem ersten Punkt traf für mich in einem RecyclerView-Artikel zu ... Es ist erstaunlich, wie ich nach 5 Jahren professioneller Android-Entwicklung immer noch Fälle finde, in denen ich mit diesen APIs
kämpfen muss
7

Das Hinzufügen von Hintergrundfarbe hat mir geholfen.

<CalendarView
    android:layout_width="match_parent"
    android:id="@+id/calendarView"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:layout_height="wrap_content"
    android:elevation="5dp"

    android:background="@color/windowBackground"

    />
Tim Glenn
quelle
4

Manchmal mag ich es background="@color/***"oder background="#ff33**"nicht, ich ersetze es background_colordurch Drawable, dann funktioniert es

ray liu
quelle
4

Wenn die Höhe immer noch nicht angezeigt wird, versuchen Sie es

    android:hardwareAccelerated="true" 

das wird dir definitiv helfen.

Rohit Lalwani
quelle
Das hat es für mich behoben. Ich hatte angenommen, dass TRUE die Standardeinstellung war, aber anscheinend zumindest in meinem Fall nicht.
Matt Robertson
3

Wenn Sie einen transparenten Hintergrund haben möchten und android:outlineProvider="bounds"für Sie nicht funktionieren, können Sie einen benutzerdefinierten ViewOutlineProvider erstellen:

class TransparentOutlineProvider extends ViewOutlineProvider {

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        Drawable background = view.getBackground();
        float outlineAlpha = background == null ? 0f : background.getAlpha()/255f;
        outline.setAlpha(outlineAlpha);
    }
}

Und stellen Sie diesen Anbieter auf Ihre transparente Ansicht ein:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

Quellen: https://code.google.com/p/android/issues/detail?id=78248#c13

[EDIT] Die Dokumentation von Drawable.getAlpha () besagt, dass es spezifisch ist, wie das Drawable das Alpha bedroht. Es ist möglich, dass immer 255 zurückgegeben wird. In diesem Fall können Sie das Alpha manuell bereitstellen:

class TransparentOutlineProvider extends ViewOutlineProvider {

    private float mAlpha;

    public TransparentOutlineProvider(float alpha) {
        mAlpha = alpha;
    }

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        outline.setAlpha(mAlpha);
    }
}

Wenn Ihr Ansichtshintergrund ein StateListDrawable mit der Standardfarbe # DDFF0000 ist, ist dies mit Alpha DDx0 / FFx0 == 0.86

transparentView.setOutlineProvider(new TransparentOutlineProvider(0.86f));
wirdil
quelle
2

Geben Sie dem für mich bearbeiteten Layout eine Hintergrundfarbe wie:

    android:background="@color/catskill_white"
    android:layout_height="?attr/actionBarSize"
    android:elevation="@dimen/dimen_5dp"
sudhakara ks
quelle
1

Ich hatte etwas Glück mit der Einstellung clipChildren="false"des übergeordneten Layouts.

Kavi
quelle
1

Ich habe einige Zeit daran gearbeitet und schließlich festgestellt, dass bei dunklem Hintergrund kein Schatten sichtbar ist

Efi G.
quelle
1

Neben der akzeptierten Antwort gibt es noch einen weiteren Grund, aufgrund dessen die Höhe möglicherweise nicht wie erwartet funktioniert, wenn die Bluelight-Filterfunktion des Telefons eingeschaltet ist.

Ich war mit diesem Problem konfrontiert, als die Höhe in meinem Gerät völlig verzerrt und unerträglich erschien. Aber die Höhe war in der Vorschau in Ordnung. Durch Ausschalten des Bluelight-Filters am Telefon wurde das Problem behoben.

Also auch nach dem Einstellen

android:outlineProvider="bounds"

Die Höhe funktioniert nicht richtig, dann können Sie versuchen, an den Farbeinstellungen des Telefons zu basteln.

Hemang Kumar
quelle
0

Ich glaube, Ihr Problem beruht auf der Tatsache, dass Sie das Höhenelement auf ein relatives Layout angewendet haben, das das übergeordnete Element ausfüllt. Das übergeordnete Element schneidet alle untergeordneten Ansichten in seiner eigenen Zeichenfläche ab (und ist die Ansicht, die den Schatten des untergeordneten Elements verarbeitet). Sie können dies beheben, indem Sie eine Elevationseigenschaft auf die oberste RelativeLayoutin Ihrer Ansichts-XML (das Root-Tag) anwenden .

FluffyC4 nicht
quelle
0

In meinem Fall waren Schriftarten das Problem.

1) Ohne dass fontFamilyich einen android:backgroundWert einstellen musste .

<TextView
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />

2) mit musste fontFamilyich android:outlineProvider="bounds"einstellung hinzufügen :

<TextView
    android:fontFamily="@font/gilroy_bold"
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:outlineProvider="bounds"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />
Soshial
quelle
0

In meinem Fall wurde dies durch eine benutzerdefinierte übergeordnete Komponente verursacht, die den Typ der Rendering-Ebene auf "Software" festlegte:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Das Entfernen dieser Zeile hat den Trick getan. Oder natürlich müssen Sie bewerten, warum dies überhaupt vorhanden ist. In meinem Fall sollte Honeycomb unterstützt werden, was weit hinter dem aktuellen Mindest-SDK für mein Projekt liegt.

ErrricP
quelle
0

Überprüfen Sie auch, ob Sie in dieser Ansicht kein Alpha ändern. Ich untersuche ein Problem, wenn ich in einigen Ansichten das Alpha mit der Höhe ändere. Sie verlieren einfach die Höhe, wenn Alpha geändert und wieder auf 1f geändert wird.

Milan Jurkulak
quelle