Android "elevasi" tidak menunjukkan bayangan


273

Saya memiliki ListView, dan dengan setiap item daftar, saya ingin menampilkan bayangan di bawahnya. Saya menggunakan fitur elevasi baru Android Lollipop untuk menetapkan Z pada Tampilan yang ingin saya buat bayangan, dan saya sudah melakukan ini secara efektif dengan ActionBar (secara teknis Toolbar di Lollipop). Saya menggunakan elevasi Lollipop, tetapi untuk beberapa alasan itu tidak menunjukkan bayangan di bawah daftar item. Berikut adalah cara mengatur tata letak setiap item daftar:

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

Namun, di sini adalah bagaimana ia menampilkan item daftar, tanpa bayangan: masukkan deskripsi gambar di sini

Saya juga mencoba yang berikut ini tanpa hasil:

  1. Atur elevasi ke ImageView dan TextViews sendiri daripada tata letak induk.
  2. Menerapkan latar belakang ke ImageView.
  3. Digunakan TranslationZ sebagai pengganti Elevation.

Saya mencoba tata letak Anda (tanpa tampilan khusus) dan menunjukkan bayangan di ponsel saya, dapatkah Anda membagikan proyek minimal yang mereproduksi masalah?
rnrneverdies

1
kemungkinan duplikat Android L FAB Bayangan tombol
naveejr

Jawaban:


384

Saya telah bermain-main dengan bayangan di Lollipop sebentar dan inilah yang saya temukan:

  1. Tampaknya ikatan orangtua ViewGroupmemotong bayangan anak-anaknya karena suatu alasan; dan
  2. bayangan yang diatur dengan batas android:elevationoleh Viewbatas, bukan batas yang diperpanjang melalui margin;
  3. cara yang tepat untuk mendapatkan tampilan anak untuk menunjukkan bayangan adalah dengan mengatur bantalan pada orang tua dan mengatur android:clipToPadding="false"pada orang tua itu.

Berikut saran saya kepada Anda berdasarkan apa yang saya ketahui:

  1. Setel level atas Anda RelativeLayoutagar memiliki padding yang sama dengan margin yang Anda tetapkan pada tata letak relatif yang ingin Anda tampilkan bayangan;
  2. atur android:clipToPadding="false"pada yang sama RelativeLayout;
  3. Hapus margin dari RelativeLayoutyang juga memiliki set ketinggian;
  4. [EDIT] Anda mungkin juga perlu mengatur warna latar belakang yang tidak transparan pada tata letak anak yang perlu ditinggikan.

Pada akhirnya, tata letak relatif tingkat atas Anda akan terlihat seperti ini:

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

Tata letak relatif interior akan terlihat seperti ini:

<RelativeLayout
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:background="[some non-transparent color]"
    android:elevation="30dp"
    >

8
Terima kasih untuk ini! Saya juga menemukan android: clipChildren = "false" berguna ketika diterapkan pada tata letak relatif induk.
blaffie

1
Senang membantu @blaffie!
Justin Pollard

214
Sangat menjengkelkan bahwa Google menghasilkan kode jelek seperti itu. Kami harus menghitung bug kerangka ini selama bertahun-tahun.
miguel

8
Google hanya mengatakan (sayangnya): " Bayangan diambil oleh induk dari tampilan yang ditinggikan, dan karenanya tunduk pada kliping tampilan standar, yang dipotong oleh induk secara default. ".
John

5
Dalam kasus saya itu adalah warna transparan. Ok, hal-hal transparan tidak membuat bayangan ... haha
Ferran Maylinch

286

Jika Anda memiliki pandangan tanpa latar belakang, baris ini akan membantu Anda

android:outlineProvider="bounds"

Secara default bayangan ditentukan oleh latar belakang tampilan, jadi jika tidak ada latar belakang, tidak akan ada bayangan juga.


11
Suatu hal yang aneh, Pratinjau menunjukkan ketinggian tetapi perangkat nyata tidak. Terima kasih, ini memperbaiki masalah.
Ioane Sharvadze

Bekerja untuk API level 21 dan lebih tinggi
Pantelis Ieronimakis

10
Ini semacam bekerja untuk saya, tetapi memberi batas diagonal di sisi ketika diterapkan pada tampilan teks. Mengatur latar belakang ke warna (sama seperti warna latar belakang orang tua) bekerja lebih baik.
Gober

4
Ini juga berlaku jika latar belakang Anda khusus dan tidak ada <solid>.
David Lord

Ini dapat digunakan secara terbalik. Ketika Anda menginginkan latar belakang yang tidak transparan dengan ketinggian dan tidak ingin bayangan. Cukup setel ke none. Terima kasih!
Odys

101

Rupanya, Anda tidak bisa hanya mengatur ketinggian pada Tampilan dan membuatnya muncul. Anda juga perlu menentukan latar belakang.

Baris berikut yang ditambahkan ke LinearLayout saya akhirnya menunjukkan bayangan:

android:background="@android:color/white"
android:elevation="10dp"

Itu tidak terduga. Saya telah mengatur ImageView dengan src dan sedang mencari solusi. Terima kasih.
Andrew Grow

47

satu hal lain yang harus Anda perhatikan, bayangan tidak akan muncul jika Anda memiliki baris ini di manifes:

android: hardwareAccelerated = "false"

Saya mencoba semua hal yang disarankan tetapi itu hanya bekerja untuk saya ketika saya menghapus garis, alasan saya memiliki garis itu karena aplikasi saya bekerja dengan sejumlah gambar bitmap dan mereka menyebabkan aplikasi mogok.


1
Ini tidak menyelesaikan masalah, jika Anda memerlukan bendera itu untuk hadir.
Clive Jefferies

Terima kasih!! Saya menghabiskan satu hari mencoba meninggikan AppBar dan menemukan masalah ketika saya memeriksa manifes untuk bendera aktivitas ini
ir2pid

1
Saya mencoba semua solusi yang mungkin, tetapi tidak ada yang berhasil untuk saya. Solusi ini berhasil. Terima kasih. Juga perlu android:clipToPadding="false"dengan solusi ini.
Chirag Savsani

29

Jika Anda memiliki pandangan tanpa latar belakang, baris ini akan membantu Anda

android:outlineProvider="bounds"

Jika Anda memiliki tampilan dengan latar belakang, baris ini akan membantu Anda

android:outlineProvider="paddedBounds"

6
Solusi ini adalah satu-satunya yang berfungsi untuk saya. Terima kasih
Oleh Liskovych

4
Ini berfungsi kecuali jika Anda memiliki jari-jari di latar belakang tampilan Anda, dalam hal ini bayangan akan menunjukkan acara sebagai persegi panjang, tetapi paddedBounds tidak berfungsi untuk tampilan dengan latar belakang.
Trevor Hart

android:outlineProvider="paddedBounds"baris ini bekerja untuk saya. Saya mengatur Selector Drawable.
Chirag Savsani

1
Ketika saya menggunakan ini, bayangan diambil sepenuhnya di dalam tampilan daripada di luar, yang bukan yang saya inginkan.
androidguy


12

Ugh, baru menghabiskan satu jam mencoba mencari tahu ini. Dalam kasus saya, saya memiliki latar belakang, namun diatur ke warna. Ini tidak cukup, Anda harus memiliki latar belakang tampilan yang ditetapkan untuk digambar.

mis. Ini tidak akan memiliki bayangan:

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

tapi ini akan

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

EDIT: Juga menemukan bahwa jika Anda menggunakan pemilih sebagai latar belakang, jika Anda tidak memiliki sudut diatur maka bayangan tidak akan muncul di jendela Pratinjau tetapi akan muncul di perangkat

mis. Ini tidak memiliki bayangan dalam pratinjau:

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

tetapi ini:

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

1
Kebalikan dari poin pertama Anda adalah benar bagi saya dalam item RecyclerView ... Sungguh menakjubkan bagaimana saya masih menemukan kasus di mana saya harus bertarung dengan API ini setelah 5 tahun pengembangan Android profesional :(
aProperFox

7

Menambahkan warna latar belakang membantu saya.

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

    />

4

Kadang suka background="@color/***"atau background="#ff33**"tidak berfungsi, saya ganti background_colordengan drawable, lalu berhasil


4

Jika masih belum menunjukkan ketinggian coba

    android:hardwareAccelerated="true" 

ini pasti akan membantu Anda.


Ini memperbaikinya untuk saya. Saya berasumsi bahwa TRUE adalah pengaturan default, tetapi ternyata tidak, setidaknya dalam kasus saya.
Matt Robertson

3

Jika Anda ingin memiliki latar belakang transparan dan android:outlineProvider="bounds"tidak bekerja untuk Anda, Anda dapat membuat ViewOutlineProvider kustom:

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

Dan atur penyedia ini ke tampilan transparan Anda:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

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

[EDIT] Dokumentasi Drawable.getAlpha () mengatakan bahwa itu khusus untuk bagaimana Drawable mengancam alpha. Ada kemungkinan bahwa itu akan selalu mengembalikan 255. Dalam hal ini Anda dapat memberikan alpha secara manual:

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

Jika latar belakang tampilan Anda adalah StateListDrawable dengan warna default # DDFF0000 yaitu dengan alpha DDx0 / FFx0 == 0,86

transparentView.setOutlineProvider(new TransparentOutlineProvider(0.86f));

2

berikan beberapa warna latar belakang untuk tata letak yang bekerja untuk saya seperti:

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

1

Saya beruntung dengan pengaturan clipChildren="false"tata letak induk.


1

Saya menghabiskan beberapa waktu mengerjakannya dan akhirnya menyadari bahwa ketika latar belakang gelap, bayangan tidak terlihat


1

Menambah jawaban yang diterima, ada satu alasan lagi karena ketinggian yang mungkin tidak berfungsi seperti yang diharapkan jika fitur filter Bluelight pada ponsel AKTIF.

Saya menghadapi masalah ini ketika ketinggian tampak sangat menyimpang dan tak tertahankan di perangkat saya. Tapi ketinggiannya baik-baik saja di pratinjau. Mematikan filter Bluelight di ponsel menyelesaikan masalah.

Begitu pun setelah pengaturan

android:outlineProvider="bounds"

Ketinggian tidak berfungsi dengan benar, maka Anda dapat mencoba mengotak-atik pengaturan warna ponsel.


0

Saya percaya masalah Anda berasal dari fakta bahwa Anda telah menerapkan elemen elevasi ke tata letak relatif yang mengisi induknya. Induknya memotong semua tampilan anak di dalam kanvas gambarnya sendiri (dan merupakan tampilan yang menangani bayangan anak). Anda dapat memperbaikinya dengan menerapkan properti elevasi ke atas RelativeLayoutdi tampilan xml Anda (tag root).


0

Dalam kasus saya font adalah masalahnya.

1) Tanpa fontFamilysaya perlu menetapkan android:backgroundbeberapa nilai.

<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) dengan fontFamilysaya harus menambahkan android:outlineProvider="bounds"pengaturan:

<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" />

0

Dalam kasus saya, ini disebabkan oleh komponen induk kustom yang menyetel jenis lapisan rendering ke "Software":

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Menghapus garis ini berhasil. Atau tentu saja Anda perlu mengevaluasi mengapa ini ada di tempat pertama. Dalam kasus saya itu adalah untuk mendukung Honeycomb, yang jauh di belakang SDK minimum saat ini untuk proyek saya.


0

Periksa juga apakah Anda tidak mengubah alpha pada tampilan itu. Saya sedang menyelidiki masalah ketika saya mengubah alpha pada beberapa tampilan, dengan elevasi. Mereka hanya kehilangan ketinggian ketika alpha diubah dan diubah kembali ke 1f.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.