การวาง / ทับซ้อนกัน (ดัชนี z) มุมมองด้านบนมุมมองอื่นใน Android


230

ฉันมีเลย์เอาต์แบบเส้นตรงซึ่งประกอบด้วยภาพและข้อความแบบอักษรซึ่งอยู่ด้านล่างหนึ่งเป็นแบบเชิงเส้น

<LinearLayout android:orientation="horizontal" ... >
 <ImageView 
     android:id="@+id/thumbnail"
     android:layout_weight="0.8" 
     android:layout_width="0dip"
     android:layout_height="fill_parent">
 </ImageView>
 <TextView 
    android:id="@+id/description"
    android:layout_weight="0.2"
    android:layout_width="0dip"
    android:layout_height="wrap_content">
 </TextView>

กฎบางอย่างอาจหายไปนี่คือเพื่อให้ความคิดว่ารูปแบบลักษณะอย่างไร ฉันต้องการมุมมองข้อความขนาดเล็กอีกอันหนึ่งที่บอกว่า 50dip ในความยาวและความกว้างวางเหนือ imageview โดย "เหนือ" ฉันหมายถึง z-index มากกว่า imageview ฉันต้องการวางสิ่งนี้ไว้ที่กึ่งกลางและด้านบน (ทับซ้อน) imageview

ฉันต้องการทราบว่าเราจะวางมุมมองหนึ่งมุมมองเหนือมุมมองอื่นได้อย่างไรด้วยดัชนี z ที่ต่างกัน (ควรอยู่ในรูปแบบเชิงเส้น)

คำตอบ:


295

คุณไม่สามารถใช้ LinearLayout นี้ FrameLayoutแต่คุณสามารถใช้ ใน a FrameLayout, z-index ถูกกำหนดโดยลำดับที่เพิ่มไอเท็มตัวอย่างเช่น:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_drawable"
        android:scaleType="fitCenter"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:padding="5dp"
        android:text="My Label"
        />
</FrameLayout>

ในตัวอย่างนี้ TextView จะถูกวาดที่ด้านบนของ ImageView ตามกึ่งกลางด้านล่างของรูปภาพ


ใช่ฉันทำโดยใช้โครงร่างตัวเองหลังจากผ่านเอกสาร ขอบคุณ.
เสาร์ที่

11
มีข้อดีของการใช้ FrameLayout แทน RelativeLayout สำหรับสิ่งนี้หรือไม่?
Ixx

12
FrameLayout ไม่เกี่ยวข้องกับมุมมองอื่นในกลุ่ม แต่เป็นเพียงเลเยอร์มุมมองเกี่ยวกับพาเรนต์ RelativeLayout นั้นใช้สำหรับวางตำแหน่งที่สัมพันธ์กับรายการอื่น ๆ
Kevin Coppock

3
สวัสดี kcoppock มือถือของฉัน (hdpi) ไม่เคารพ z-order ในโครงร่างเฟรม แต่ฉันมีอีกอันหนึ่ง (xhdpi) และเคารพคำสั่งนี้คุณรู้ไหมว่าทำไมถึงทำเช่นนี้? ขอบคุณล่วงหน้า! : D
Merlí Escarpenter Pérez

1
ในฐานะของ API 21 / KitKat ตอนนี้คุณสามารถใช้ setZ และ translationZ; ไม่จำเป็นต้องแฮ็ค FrameLayout อีกต่อไป (ในที่สุด!) นี่ควรเป็นคำตอบที่ต้องการสำหรับการพัฒนา 5.0+ ที่ทันสมัย: stackoverflow.com/a/29703860/358578
pbarranis

183

3
เราสามารถใช้สิ่งนี้ในไฟล์ xml ได้หรือไม่?
โฆษณา

2
ฉันกำลังมองหาบางสิ่งบางอย่างที่จะนำมุมมองของฉันไปเปลี่ยน itz zindex ในระหว่างการแปลแอนิเมชัน
DeltaCap019

คุณสามารถหาวิธีแก้ปัญหาสำหรับแอนิเมชันการแปลได้ไหม?
nAkhmedov

9
bringChildToFront () เพียงแค่เปลี่ยนดัชนีของมุมมองภายในแม่
Zar E Ahmer

4
สกรูนี้เรียงลำดับเค้าโครงทั้งหมด
Jemshit Iskenderov

66

RelativeLayout ทำงานในลักษณะเดียวกันรูปภาพสุดท้ายในเค้าโครงที่สัมพันธ์กันชนะ


14
นอกจากว่าคุณจะใช้ระดับความสูงคุณต้องมีค่ามากที่สุด
Sami Kuhmonen

5
คำถามนี้ถูกถามและตอบก่อนที่จะมีการยกระดับ การใช้ระดับความสูงจะไม่แก้ไขปัญหาหากแอปของคุณมี minSdk น้อยกว่า Lollipop (บนโทรศัพท์ก่อนอมยิ้มรูปแบบจะดูผิดถ้าคุณพึ่งพาระดับความสูง) - คุณยังต้องใส่ใจกับลำดับของการจัดวาง คุณคิดถูกว่าถ้าคุณใช้ระดับความสูงที่ส่วนประกอบด้านล่าง - คุณต้องมีอย่างน้อยเหมือนกันหรือสูงกว่าอยู่ด้านบน
jt-gilkeson

27

การเปลี่ยนลำดับการวาด

อีกทางเลือกหนึ่งคือเปลี่ยนลำดับการดูโดยผู้ปกครอง คุณสามารถเปิดใช้งานคุณลักษณะนี้จาก ViewGroup โดยการเรียกsetChildrenDrawingOrderEnabled (จริง)และเอาชนะgetChildDrawingOrder (int childCount, int i)

ตัวอย่าง:

/**
 * Example Layout that changes draw order of a FrameLayout
 */
public class OrderLayout extends FrameLayout {

    private static final int[][] DRAW_ORDERS = new int[][]{
            {0, 1, 2},
            {2, 1, 0},
            {1, 2, 0}
    };

    private int currentOrder;

    public OrderLayout(Context context) {
        super(context);
        setChildrenDrawingOrderEnabled(true);
    }

    public void setDrawOrder(int order) {
        currentOrder = order;
        invalidate();
    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        return DRAW_ORDERS[currentOrder][i];
    }
}

เอาท์พุท:

การโทรOrderLayout#setDrawOrder(int)ด้วยผลลัพธ์ 0-1-2 ใน:

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


คุณเรียก setDrawOrder (i) ในกิจกรรม onCreate () หรือไม่? หากฉันมี 6 วิดเจ็ตใน xml ฉันต้องเริ่มต้น DRAW_ORDERS แต่ละแถวด้วยตัวเลข 6 ตัว (0-5) หรือไม่
จอห์นวอร์ด

@JohnWard เลย์เอาต์ที่แสดงด้านบนมีวัตถุประสงค์เพื่อเป็นตัวอย่างเท่านั้นคุณสามารถกำหนดพฤติกรรมของคุณเองใน getChildDrawingOrder ()
Tobrun

นี่คือการโพสต์ที่เกี่ยวข้องกับรหัสที่ชัดเจนมาก: stackoverflow.com/questions/20524162/framelayout-in-reverse
Robert

20

คุณสามารถใช้การview.setZ(float)เริ่มต้นจาก API ระดับ 21 ที่นี่คุณสามารถค้นหาข้อมูลเพิ่มเติมได้


3
ตอนนี้ควรเป็นคำตอบที่ต้องการสำหรับ API 21 / KitKat / 5.0 หรือสูงกว่า แฮ็กกรอบเลย์เอาต์เก่าไม่จำเป็นต้องขอบคุณอีกต่อไป โดยส่วนตัวฉันไม่เข้าใจความแตกต่างระหว่าง setZ และ translationZ แต่สิ่งหลังคือคุณลักษณะและทำงานได้อย่างสวยงามสำหรับฉัน ขอบคุณ!
pbarranis

สำหรับ apis ก่อนหน้านี้คุณสามารถใช้ ViewCompat # setZ () ได้เช่นกัน
Ali Yucel Akgul

@AliYucelAkgul หากดูเอกสารที่นี่Compatibility: API < 21: No-op คุณสามารถดู ดังนั้นฉันคิดว่ามันจะไม่ทำงาน
Vadim Kotov

@VadimKotov ฉันลองในแอพแล้วมันใช้งานได้
Ali Yucel Akgul

@AliYucelAkgul ดีว่าแปลก อาจผิดพลาดในเอกสารหรือไม่ คุณแน่ใจ 100% ว่าใช้งานได้กับ API <21 หรือไม่ ผมมีความคิดว่ามันสามารถเปลี่ยนลำดับของมุมมองสำหรับ API ก่อนหน้านี้ แต่ไม่มีสิ่งแฟนซีเช่นระดับความสูง ฯลฯ ..
Vadim Kotov

14

ฉันแก้ไขปัญหาเดียวกันด้วยการเพิ่มandroid:elevation="1dp"มุมมองที่คุณต้องการให้กับอีกมุมมองหนึ่ง แต่มันไม่สามารถแสดงได้ต่ำกว่า 5.0 และมันจะมีเงาเล็กน้อยหากคุณยอมรับมันก็โอเค

ดังนั้นทางออกที่ถูกต้องที่สุดคือ @kcoppock กล่าว


7

ลองสิ่งนี้ใน RelativeLayout:

ImageView image = new ImageView(this);
image.SetZ(float z);

มันใช้งานได้สำหรับฉัน


2
คุณควรอธิบายให้ดีขึ้นสักหน่อย ตัวอย่างเช่นคุณจะใส่รหัสนี้ที่ไหน
DevB2F

ฉันก็ใส่ไว้ในวิธี OnCreate () แต่ละภาพที่เพิ่มมีดัชนี z ของการตั้งค่ามากกว่าคนที่เพิ่มมาก่อน ฉันหมายถึงผ่านดัชนี z ฉันสามารถเปลี่ยนตำแหน่งของถัดไปหลังก่อนหน้านี้
Rizzo

5

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

<linearLayout android:orientation="horizontal" ... >
<ImageView 
 android:id="@+id/thumbnail"
 android:layout_weight="0.8" 
 android:layout_width="0dip"
 android:layout_height="fill_parent"
>
</ImageView>
<TextView 
android:id="@+id/description"
android:layout_marginTop="-20dip"
android:layout_weight="0.2"
android:layout_width="0dip"
android:layout_height="wrap_content"
>
</TextView>

4

AFAIK คุณไม่สามารถทำมันได้ด้วยรูปแบบเชิงเส้นที่คุณจะต้องไปหาRelativeLayout


RelativeLayout ไม่ขยาย frameLayout คุณแน่ใจหรือว่าจะใช้งานได้?
ekatz

มันจะ. คุณสามารถใช้ FrameLayout หรือ RelativeLayout ใดก็ได้ แต่ละคนมีวิธีที่แตกต่างกันในการวางมุมมองของเด็ก อ้างถึงเอกสารเพื่อทราบข้อมูลเพิ่มเติมเกี่ยวกับเค้าโครงเหล่านั้น
Vincent Mimoun-Prat

นี่คือหนทางไป
อัลเบิร์ตเจมส์เทดดี้

0

หากคุณเพิ่มมุมมองโดยทางโปรแกรมคุณสามารถใช้ yourLayout.addView(view, 1);

1 is the indexที่ไหน


0

ฉันใช้สิ่งนี้หากคุณต้องการให้มีมุมมองเดียวที่จะนำมาไว้ข้างหน้าเมื่อต้องการ:

containerView.bringChildToFront(topView);

containerViewเป็นคอนเทนเนอร์ของมุมมองที่จะเรียงลำดับtopViewเป็นมุมมองที่ฉันต้องการมีด้านบนมากที่สุดในภาชนะ

สำหรับมุมมองที่หลากหลายในการจัดเรียงกำลังจะใช้ setChildrenDrawingOrderEnabled (จริง) และแทนที่ getChildDrawingOrder (int childCount, int i) ตามที่กล่าวไว้ข้างต้น

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