Đặt / chồng lấp (chỉ mục z) một chế độ xem trên một chế độ xem khác trong Android


230

Tôi có một bố cục tuyến tính bao gồm hình ảnh và textview, cái này nằm dưới cái kia trong bố cục tuyến tính.

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

Một số quy tắc có thể bị thiếu, điều này là để đưa ra một ý tưởng, cách bố trí trông như thế nào. Tôi muốn một chế độ xem văn bản nhỏ khác có chiều dài và chiều rộng 50dip, được đặt trên chế độ xem hình ảnh, bằng cách "trên" Tôi có nghĩa là chỉ số z nhiều hơn số lần xem hình ảnh, tôi muốn đặt cái này ở giữa và trên (chồng chéo) số lần xem hình ảnh.

Tôi muốn biết làm thế nào chúng ta có thể đặt một chế độ xem trên cái kia, với chỉ số z khác nhau (tốt nhất là trong bố cục tuyến tính)?

Câu trả lời:


295

Bạn không thể sử dụng linearLayout cho việc này, nhưng bạn có thể sử dụng một FrameLayout. Trong a FrameLayout, chỉ số z được xác định theo thứ tự các mục được thêm vào, ví dụ:

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

Trong trường hợp này, TextView sẽ được vẽ ở trên cùng của ImageView, dọc theo trung tâm dưới cùng của hình ảnh.


Vâng, tôi đã làm nó bằng cách sử dụng bố cục khung sau khi đi qua tài liệu. Cảm ơn bạn.
ngồi

11
Có lợi thế nào khi sử dụng FrameLayout thay vì RelativeLayout cho việc này không?
Ixx

12
FrameLayout không liên quan đến các chế độ xem khác trong nhóm, nó chỉ xếp lớp chúng liên quan đến cha mẹ. RelativeLayout dành cho việc định vị so với các mục khác.
Kevin Coppock

3
Xin chào kcoppock điện thoại di động của tôi (hdpi) không tôn trọng thứ tự z trong bố cục khung, nhưng tôi có một (xhdpi) khác và tôn trọng thứ tự này, bạn có biết tại sao làm điều này không? Cảm ơn trước! : D
Merlí Escarpenter Pérez

1
Kể từ API 21 / KitKat, giờ đây bạn có thể sử dụng setZ và dịchZ; hack FrameLayout không còn cần thiết nữa (cuối cùng!). Đây phải là câu trả lời ưa thích cho sự phát triển 5.0+ hiện đại: stackoverflow.com/a/29703860/358578
pbarranis 24/2/2016

183

3
chúng ta có thể sử dụng điều này trong các tập tin xml không?
Quảng cáo

2
Tôi đang tìm kiếm một cái gì đó như vậy để đưa quan điểm của tôi thay đổi itz zindex trong quá trình dịch hoạt hình.
DeltaCap019

Bạn có thể tìm một giải pháp cho hoạt hình dịch?
nAkhmedov

9
bringChildToFront () chỉ thay đổi chỉ mục của Chế độ xem bên trong cha mẹ của nó
Zar E Ahmer

4
điều này làm
hỏng

66

RelativeLayout hoạt động theo cách tương tự, hình ảnh cuối cùng trong bố cục tương đối sẽ thắng.


14
Trừ khi bạn sử dụng độ cao, thì bạn cũng cần giá trị lớn nhất trong đó.
Sami Kuhmonen

5
Câu hỏi này đã được hỏi và trả lời trước khi độ cao tồn tại. Sử dụng độ cao sẽ không khắc phục được sự cố nếu ứng dụng của bạn có minSdk nhỏ hơn Lollipop (trên điện thoại tiền kẹo, bố cục sẽ có vẻ sai nếu bạn chỉ dựa vào độ cao) - bạn vẫn phải chú ý đến thứ tự bố cục. Mặc dù vậy, bạn đã đúng, nếu bạn sử dụng độ cao ở thành phần dưới cùng - bạn chắc chắn cần phải có ít nhất bằng hoặc cao hơn ở trên cùng.
jt-gilkeson

27

Thay đổi thứ tự bốc thăm

Một cách khác là thay đổi thứ tự các khung nhìn được vẽ bởi cha mẹ. Bạn có thể kích hoạt tính năng này từ Viewgroup bằng cách gọi setChildrenDrawingOrderEnables (true) và ghi đè getChildDrawingOrder (int childCount, int i) .

Thí dụ:

/**
 * 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];
    }
}

Đầu ra:

Gọi OrderLayout#setDrawOrder(int)với kết quả 0-1-2 trong:

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


Bạn có gọi setDrawOrder (i) trong hoạt động onCreate () không? Nếu tôi có 6 widget trong xml, tôi có cần khởi tạo từng hàng DRAW_ORDERS với một mảng gồm 6 số (0-5) không?
John Ward

@JohnWard bố cục hiển thị ở trên chỉ dành cho mục đích ví dụ, bạn có thể xác định hành vi của riêng mình trong getChildDrawingOrder ().
Toban

Đây là bài đăng liên quan với nhiều mã rõ ràng: stackoverflow.com/questions/20524162/framelayout-in-reverse
Robert

20

Bạn có thể sử dụng view.setZ(float)bắt đầu từ API cấp 21. Tại đây bạn có thể tìm thêm thông tin.


3
Đây sẽ là câu trả lời ưa thích cho API 21 / KitKat / 5.0 trở lên. Bản hack frameLayout cũ rất may không còn cần thiết nữa. Cá nhân tôi không hiểu sự khác biệt giữa setZ và dịchZ, nhưng cái sau là một thuộc tính và hoạt động rất tốt đối với tôi. Cảm ơn!
pbarranis

Đối với các apis trước, bạn cũng có thể sử dụng ViewCompat # setZ ().
Ali Yucel Akgul

@AliYucelAkgul nếu bạn xem các tài liệu ở đây , bạn có thể thấy Compatibility: API < 21: No-op . Vì vậy, tôi nghĩ rằng nó sẽ không hoạt động
Vadim Kotov

@VadimKotov, tôi đã thử trong ứng dụng của mình và nó chỉ hoạt động.
Ali Yucel Akgul

@AliYucelAkgul tốt, thật lạ. Có lẽ một sai lầm trong các tài liệu? Bạn có chắc chắn 100% nó đang hoạt động cho API <21? Tôi có một ý tưởng rằng nó có thể thay đổi thứ tự lượt xem cho các API trước đó, nhưng không có nội dung ưa thích nào như độ cao, v.v.
Vadim Kotov

14

Tôi đã giải quyết vấn đề tương tự bằng cách thêm android:elevation="1dp"vào chế độ xem mà bạn muốn giải quyết . Nhưng nó không thể hiển thị dưới 5.0 và nó sẽ có một bóng nhỏ, nếu bạn có thể chấp nhận nó, nó ổn.

Vì vậy, giải pháp chính xác nhất là @kcoppock nói.


7

Hãy thử điều này trong RelativeLayout:

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

Nó làm việc cho tôi.


2
Bạn nên giải thích tốt hơn một chút. Ví dụ, nơi bạn sẽ đặt mã này?
DevB2F

Vâng, tôi đặt nó trong phương thức OnCreate (). Mỗi hình ảnh được thêm vào có một chỉ số ưu tiên z so với những hình ảnh được thêm vào trước đó. Ý tôi là, thông qua chỉ số z tôi có thể thay đổi vị trí của cái tiếp theo sau cái trước.
Rizzo

5

Có một cách để sử dụng linearLayout. Chỉ cần đặt lềTop của phần tử trước của bạn thành giá trị âm tương ứng và đảm bảo phần tử bạn muốn ở trên nằm sau phần tử bạn muốn bên dưới trong XML của bạn.

<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 bạn không thể làm điều đó với bố cục tuyến tính, bạn sẽ phải đi RelativeLayout .


RelativeLayout không mở rộng frameLayout, bạn có chắc chắn rằng nó sẽ hoạt động?
ekatz

Nó sẽ. Bạn có thể sử dụng bất kỳ FrameLayout hoặc RelativeLayout. Mỗi người có cách đặt quan điểm khác nhau. Tham khảo các tài liệu để biết thêm về các bố trí.
Vincent Mimoun-Prat

đây là con đường để đi
Albert James Teddy

0

Nếu bạn đang thêm Chế độ xem theo chương trình, bạn có thể sử dụng yourLayout.addView(view, 1);

nơi 1 is the index.


0

Tôi sử dụng cái này, nếu bạn muốn chỉ có một khung nhìn được đưa ra phía trước khi cần:

containerView.bringChildToFront(topView);

containerView là nơi chứa các khung nhìn được sắp xếp, topView là khung nhìn mà tôi muốn có nhiều nhất trong vùng chứa.

cho nhiều chế độ xem sắp xếp sắp sử dụng setChildrenDrawingOrderEnables (true) và ghi đè getChildDrawingOrder (int childCount, int i) như đã đề cập ở trên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.