Android“ ยกระดับ” ไม่แสดงเงา


273

ฉันมี ListView และมีรายการแต่ละรายการที่ฉันต้องการให้แสดงเงาใต้ ฉันกำลังใช้คุณสมบัติการยกระดับใหม่ของ Android Lollipop เพื่อตั้งค่า Z บนมุมมองที่ฉันต้องการสร้างเงาและฉันกำลังทำสิ่งนี้อย่างมีประสิทธิภาพด้วย ActionBar (ในทางเทคนิคแล้ว Toolbar ใน Lollipop) ฉันใช้ระดับความสูงของ Lollipop แต่ด้วยเหตุผลบางอย่างมันไม่แสดงเงาภายใต้รายการ นี่คือวิธีการตั้งค่าเค้าโครงของแต่ละรายการ:

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

อย่างไรก็ตามนี่คือวิธีแสดงรายการโดยไม่มีเงา: ป้อนคำอธิบายรูปภาพที่นี่

ฉันได้ลองทำสิ่งต่อไปนี้เพื่อประโยชน์:

  1. ตั้งค่าระดับความสูงเป็น ImageView และ TextViews ด้วยตนเองแทนที่จะเป็นเค้าโครงหลัก
  2. นำพื้นหลังไปใช้กับ ImageView
  3. ใช้ TranslationZ แทนการยกระดับ

ฉันลองเลย์เอาต์ของคุณ (โดยไม่ต้องมีการแสดงตัวอย่าง) และแสดงเงาในโทรศัพท์ของคุณคุณสามารถแชร์โปรเจ็กต์ขนาดเล็กที่สุดที่ทำให้เกิดปัญหาซ้ำได้หรือไม่?
rnrneverdies

1
เป็นไปได้ที่ซ้ำกันของเงาปุ่ม
LAB

คำถามที่เกี่ยวข้อง: stackoverflow.com/questions/26572048/…
stefan222

คำตอบ:


384

ฉันเล่นกับเงาบน Lollipop มาบ้างแล้วและนี่คือสิ่งที่ฉันได้พบ:

  1. ปรากฏว่าViewGroupขอบเขตของผู้ปกครองตัดเงาของเด็กด้วยเหตุผลบางอย่าง; และ
  2. เงาที่ถูกกำหนดด้วยandroid:elevationถูกตัดออกโดยViewขอบเขตของไม่ใช่ขอบเขตที่ขยายผ่านขอบ
  3. วิธีที่ถูกต้องในการรับมุมมองเด็กเพื่อแสดงเงาคือการกำหนดช่องว่างภายในบนพาเรนต์และตั้งandroid:clipToPadding="false"บนพาเรนต์นั้น

นี่คือข้อเสนอแนะของฉันให้คุณตามสิ่งที่ฉันรู้:

  1. ตั้งค่าระดับบนสุดของคุณRelativeLayoutให้มีช่องว่างภายในเท่ากับระยะขอบที่คุณได้กำหนดไว้ในเค้าโครงแบบสัมพันธ์ที่คุณต้องการแสดงเงา
  2. ตั้งandroid:clipToPadding="false"อยู่บนเดียวกันRelativeLayout;
  3. ลบระยะขอบจากส่วนRelativeLayoutที่มีระดับความสูง
  4. [แก้ไข] คุณอาจต้องตั้งค่าสีพื้นหลังแบบไม่โปร่งใสบนเลย์เอาต์ลูกที่ต้องการระดับความสูง

ในตอนท้ายของวันเลย์เอาต์ระดับสูงสุดของคุณควรมีลักษณะดังนี้:

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

เค้าโครงที่สัมพันธ์กันของการตกแต่งภายในควรมีลักษณะดังนี้:

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

8
ขอบคุณสำหรับสิ่งนี้! ฉันยังพบ android: clipChildren = "false" เพื่อเป็นประโยชน์เมื่อนำไปใช้กับเค้าโครงสัมพันธ์หลัก
blaffie

1
ดีใจที่ได้ช่วย @blaffie!
Justin Pollard

214
มันน่ารำคาญมากที่ Google ผลิตรหัสต่ำ ๆ เราจะต้องพิจารณาข้อผิดพลาดของเฟรมเวิร์กเหล่านี้เป็นเวลาหลายปี
miguel

8
Google กล่าวว่า (อนิจจา) เท่านั้น: " เงาถูกดึงโดยพาเรนต์ของมุมมองที่ยกระดับและดังนั้นจึงขึ้นอยู่กับการตัดมุมมองมาตรฐานโดยผู้ปกครองจะถูกตัดเป็นค่าเริ่มต้น "
จอห์น

5
ในกรณีของฉันมันเป็นสีโปร่งใส โอเคสิ่งที่โปร่งใสไม่ทำให้เกิดเงา ... ฮ่าฮ่า
Ferran Maylinch

286

หากคุณมีมุมมองที่ไม่มีพื้นหลังบรรทัดนี้จะช่วยคุณ

android:outlineProvider="bounds"

โดยค่าเริ่มต้นเงาจะถูกกำหนดโดยพื้นหลังของมุมมองดังนั้นหากไม่มีพื้นหลังก็จะไม่มีเงาด้วย


11
เป็นสิ่งที่แปลกอย่าง Preview แสดงให้เห็นว่าระดับความสูง แต่อุปกรณ์จริงไม่ได้ ขอบคุณสิ่งนี้แก้ไขปัญหาได้แล้ว
Ioane Sharvadze

ใช้งานได้กับ API ระดับ 21 ขึ้นไป
Pantelis Ieronimakis

10
การเรียงลำดับนี้เหมาะกับฉัน แต่ให้เส้นทแยงมุมที่ด้านข้างเมื่อนำไปใช้กับมุมมอง การตั้งค่าพื้นหลังเป็นสี (เช่นเดียวกับสีพื้นหลังของผู้ปกครอง) ทำได้ดีกว่า
Gober

4
<solid>นอกจากนี้ยังนำถ้าพื้นหลังของคุณเป็นที่กำหนดเองและไม่เคยมีใคร
เดวิดลอร์ด

สิ่งนี้สามารถใช้ในการย้อนกลับ เมื่อคุณต้องการพื้นหลังแบบไม่โปร่งใสพร้อมระดับความสูงและไม่ต้องการเงา noneเพียงแค่ตั้งค่าให้ ขอบคุณ!
Odys

101

เห็นได้ชัดว่าคุณไม่สามารถตั้งค่าระดับความสูงบนมุมมองและให้ปรากฏ คุณต้องระบุพื้นหลังด้วย

ในที่สุดบรรทัดต่อไปนี้ที่เพิ่มลงใน LinearLayout ของฉันก็แสดงเงา:

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

มันเป็นสิ่งที่ไม่คาดคิด ฉันตั้ง ImageView ด้วย src แล้วและกำลังมองหาวิธีแก้ปัญหา ขอบคุณ.
Andrew Grow

47

อีกสิ่งหนึ่งที่คุณควรระวังเงาจะไม่ปรากฏหากคุณมีบรรทัดนี้ในรายการ:

หุ่นยนต์: hardwareAccelerated = "false"

ฉันลองทุกสิ่งที่แนะนำ แต่ใช้งานได้เฉพาะฉันเมื่อฉันลบบรรทัดเหตุผลที่ฉันมีบรรทัดนั้นเป็นเพราะแอปของฉันทำงานกับรูปภาพบิตแมปจำนวนหนึ่งและพวกเขาทำให้แอปขัดข้อง


1
วิธีนี้ไม่ได้แก้ปัญหาหากคุณต้องการให้มีการตั้งค่าสถานะนั้น
ไคลฟ์ Jefferies

ขอบคุณ!! ฉันใช้เวลาหนึ่งวันในการยกระดับ AppBar และพบปัญหาเมื่อฉันตรวจสอบรายการสำหรับกิจกรรมนี้ธง
ir2pid

1
ฉันลองวิธีแก้ปัญหาที่เป็นไปได้ทั้งหมด แต่ก็ไม่ได้ผลสำหรับฉัน วิธีนี้ใช้ได้ผล ขอบคุณ ยังต้องใช้android:clipToPadding="false"กับโซลูชั่นนี้
Chirag Savsani

29

หากคุณมีมุมมองที่ไม่มีพื้นหลังบรรทัดนี้จะช่วยคุณ

android:outlineProvider="bounds"

หากคุณมีมุมมองพร้อมพื้นหลังบรรทัดนี้จะช่วยคุณ

android:outlineProvider="paddedBounds"

6
วิธีนี้เป็นวิธีเดียวที่ใช้ได้ผลสำหรับฉัน ขอบคุณ
Oleh Liskovych

4
วิธีนี้ใช้งานได้เว้นแต่ว่าคุณมีรัศมีบนพื้นหลังมุมมองของคุณในกรณีนี้เงาจะแสดงเป็นรูปสี่เหลี่ยมผืนผ้า แต่ paddedBounds จะทำงานสำหรับมุมมองที่มีพื้นหลัง
เทรเวอร์ฮาร์ต

android:outlineProvider="paddedBounds"บรรทัดนี้ใช้ได้สำหรับฉัน ฉันตั้งค่าตัวเลือก Drawable
Chirag Savsani

1
เมื่อฉันใช้สิ่งนี้เงาจะถูกวาดในมุมมองมากกว่าด้านนอกซึ่งไม่ใช่สิ่งที่ฉันต้องการ
androidguy


12

เอ่อเพิ่งใช้เวลาหนึ่งชั่วโมงเพื่อที่จะคิดออก ในกรณีของฉันฉันมีชุดพื้นหลัง แต่มันถูกตั้งค่าเป็นสี ไม่เพียงพอคุณต้องมีพื้นหลังของชุดมุมมองเป็นแบบวาดได้

เช่นนี้จะไม่มีเงา:

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

แต่สิ่งนี้จะ

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

แก้ไข: ได้ค้นพบว่าหากคุณใช้ตัวเลือกเป็นพื้นหลังหากคุณไม่มีชุดมุมแล้วเงาจะไม่ปรากฏในหน้าต่างแสดงตัวอย่างแต่จะปรากฏขึ้นบนอุปกรณ์

เช่นนี้ไม่มีเงาในภาพตัวอย่าง:

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

แต่สิ่งนี้จะ:

<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
ตรงข้ามกับจุดแรกของคุณเป็นจริงสำหรับฉันในรายการ RecyclerView ... มันน่าอัศจรรย์ที่ฉันยังคงค้นหากรณีที่ฉันต้องต่อสู้กับ API เหล่านี้หลังจาก 5 ปีของการพัฒนา Android มืออาชีพ :(
aProperFox

7

การเพิ่มสีพื้นหลังช่วยฉันได้

<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

บางครั้งชอบbackground="@color/***"หรือbackground="#ff33**"ไม่ทำงานฉันแทนที่background_colorด้วย drawable จากนั้นก็ใช้งานได้


4

หากยังไม่แสดงระดับความสูงให้ลอง

    android:hardwareAccelerated="true" 

สิ่งนี้จะช่วยคุณได้อย่างแน่นอน


สิ่งนี้แก้ไขได้สำหรับฉัน ฉันสันนิษฐานว่า TRUE เป็นค่าเริ่มต้น แต่อย่างน้อยก็ในกรณีของฉัน
Matt Robertson

3

หากคุณต้องการพื้นหลังโปร่งใสและandroid:outlineProvider="bounds"ไม่ได้ผลสำหรับคุณคุณสามารถสร้าง ViewOutlineProvider แบบกำหนดเอง:

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

และตั้งค่าผู้ให้บริการนี้เป็นมุมมองโปร่งใสของคุณ:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

แหล่งที่มา: https://code.google.com/p/android/issues/detail?id=78248#c13

[แก้ไข] เอกสารของ Drawable.getAlpha () บอกว่าเป็นข้อมูลเฉพาะเกี่ยวกับวิธีที่ Drawable คุกคามอัลฟา เป็นไปได้ว่ามันจะกลับมา 255 เสมอในกรณีนี้คุณสามารถให้อัลฟาด้วยตนเอง:

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

ถ้าพื้นหลังมุมมองของคุณเป็น StateListDrawable ด้วยสีเริ่มต้น # DDFF0000 ที่มีตัวอักษร DDx0 / FFx0 == 0.86

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

2

ให้สีพื้นหลังกับเค้าโครงที่ทำงานสำหรับฉันชอบ:

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


1

ฉันใช้เวลาทำงานกับมันและในที่สุดก็รู้ว่าเมื่อพื้นหลังมืดเงาจะมองไม่เห็น


1

การเพิ่มคำตอบที่ยอมรับมีอีกเหตุผลหนึ่งเนื่องจากการยกระดับอาจไม่ทำงานอย่างที่คาดไว้หากคุณสมบัติตัวกรอง Bluelight บนโทรศัพท์เปิดอยู่

ฉันกำลังเผชิญกับปัญหานี้เมื่อระดับความสูงผิดเพี้ยนและไม่สามารถทนได้ในอุปกรณ์ของฉัน แต่การยกระดับนั้นทำได้ดีในการแสดงตัวอย่าง การปิดตัวกรอง Bluelight บนโทรศัพท์สามารถแก้ไขปัญหาได้

ดังนั้นแม้หลังจากการตั้งค่า

android:outlineProvider="bounds"

ระดับความสูงไม่ทำงานอย่างถูกต้องจากนั้นคุณสามารถลองคนจรจัดด้วยการตั้งค่าสีของโทรศัพท์


0

เราเชื่อว่าปัญหาของคุณเกิดจากความจริงที่ว่าคุณได้ใช้องค์ประกอบระดับความสูงกับเค้าโครงที่สัมพันธ์กันที่เติมแม่ของมัน ผู้ปกครองของมันคลิปมุมมองเด็กทั้งหมดภายในผืนผ้าใบของตัวเอง (และเป็นมุมมองที่จัดการเงาของเด็ก) คุณสามารถแก้ไขปัญหานี้ได้โดยใช้คุณสมบัติการยกระดับให้อยู่ในระดับสูงสุดRelativeLayoutในมุมมอง xml (แท็กรูท)


0

ในกรณีของฉันแบบอักษรมีปัญหา

1) หากไม่มีfontFamilyฉันจำเป็นต้องตั้งค่าandroid:backgroundบางค่า

<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) fontFamilyฉันต้องเพิ่มandroid:outlineProvider="bounds"การตั้งค่า:

<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

ในกรณีของฉันนี้เกิดจากองค์ประกอบหลักที่กำหนดเองการตั้งค่าประเภทเลเยอร์การแสดงผลเป็น "ซอฟต์แวร์":

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

เคล็ดลับในการลบบรรทัดนี้ออก หรือแน่นอนคุณต้องประเมินว่าทำไมถึงเกิดขึ้นในตอนแรก ในกรณีของฉันมันคือการสนับสนุน Honeycomb ซึ่งอยู่หลัง SDK ขั้นต่ำปัจจุบันสำหรับโครงการของฉัน


0

ตรวจสอบด้วยหากคุณไม่เปลี่ยนอัลฟาในมุมมองนั้น ฉันกำลังตรวจสอบปัญหาเมื่อฉันเปลี่ยนอัลฟ่าในบางมุมมองด้วยระดับความสูง พวกเขาเพียงแค่ยกระดับความหลวมเมื่ออัลฟาเปลี่ยนและเปลี่ยนกลับเป็น 1f

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.