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.
AggieDev
sumber
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
Pertanyaan terkait: stackoverflow.com/questions/26572048/…
stefan222

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"
    >
Justin Pollard
sumber
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.

Dmitry Ryadnenko
sumber
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"
John Slavick
sumber
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.

nada
sumber
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"
Deepak sharma
sumber
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>
odiggitas
sumber
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"

    />
Tim Glenn
sumber
4

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

ray liu
sumber
4

Jika masih belum menunjukkan ketinggian coba

    android:hardwareAccelerated="true" 

ini pasti akan membantu Anda.

Rohit Lalwani
sumber
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));
wirdil
sumber
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"
sudhakara ks
sumber
1

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

Kavi
sumber
1

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

Efi G
sumber
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.

Hemang Kumar
sumber
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).

FluffyC4tidak
sumber
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" />
soshial
sumber
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.

ErrricP
sumber
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.

Milan Jurkulak
sumber