Визначення Z порядку переглядів RelativeLayout в Android


226

Я хотів би визначити порядок z переглядів RelativeLayout в Android.

Я знаю, що одним із способів цього є дзвінок bringToFront.

Чи є кращий спосіб зробити це? Було б чудово, якби я міг визначити порядок z у макеті xml.


4
View.bringToFront (); є
ансер

Відповіді:


314

Найпростіший спосіб - просто звернути увагу на порядок додавання переглядів у ваш XML-файл. Опускання файлу вниз означає вище вгору по осі Z.

Редагувати: це задокументовано тут і тут на сайті розробника Android. (Дякую @flightplanner)


16
На жаль, це не завжди можливо змінити. Наприклад, у відносному макеті кожен елемент може бути викладений лише стосовно тих, які були визначені раніше у файлі
Casebash

67
Casebash, я не думаю, що це неодмінно у випадку, коли ви просто повинні використовувати "@ + id / your_element_before_its_defined", а потім використовувати той самий ідентифікатор в елементі, який ви визначите пізніше. Я можу помилятися з цього приводу, ці схеми для мене дуже складні, але я безумовно складаю враження, що це працює.
tjb

7
tjb має рацію (і я радий, що він є). Використовуйте @ + id з першою згадкою про id, наприклад layout_above = "@ + id / some_id"
Michiel

3
Ви також можете помістити <item type = "id" name = "<your_id>" /> у файл значень xml, а потім ви можете посилатися на нього будь-де.
karl

8
Я знаю, що я спізнююсь на 3 роки на вечірку, але у відповідь на @hpique, це задокументовано тут
HexAndBugs


68

Зверніть увагу, кнопки та інші елементи в API 21 і вище мають високу висоту, і тому ігноруйте порядок елементів xml незалежно від батьківського макета. Зайняв мене час, щоб зрозуміти це.


16
рішенням цієї помилки для мене було викликати setElevation (1000) на зображенні, яке я хочу винести через кнопку.
вогонь у норі

setElevation () вимагає рівня API 21
dp2050

21

В Android, починаючи з рівня 21 API, елементи у файлі компонування отримують свій порядок Z як від того, як вони впорядковані у файлі, як описано у правильній відповіді, так і від їх висоти, більш високе значення висоти означає, що елемент отримує більш високий Z порядок .

Іноді це може спричинити проблеми, особливо з кнопками, які часто з’являються вгорі елементів, які відповідно до порядку XML повинні знаходитись під ними в Z порядку. Щоб виправити це, просто встановіть android:elevationелементи XML у макеті, щоб вони відповідали порядку, який ви хочете досягти.

Якщо ви встановите висоту елемента в макеті, він почне кидати тінь. Якщо ви не хочете цього ефекту, ви можете видалити тінь з таким кодом:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   myView.setOutlineProvider(null);
}

Я не знайшов жодного способу видалити тінь піднесеного виду через макет xml.


1
Як зазначено в коментарях, ви можете використовувати android:elevation="1000dp". Жодна тінь не відображається таким чином.
Вадим Котов

15

Я зіткнувся з тими ж проблемами: У відносному компонуванні parentView у мене є 2 дитини childView1 та childView2. Спочатку я поставив childView1 над childView2, і я хочу, щоб childView1 опинився поверх childView2. Зміна порядку переглядів дітей не вирішила для мене проблеми. Що для мене працювало - це встановити android: clipChildren = "false" у parentView та в коді, який я встановив:

childView1.bringToFront();

parentView.invalidate();

2
Це працює, і Android мене дуже сумує. child.bringToFront()з parent.invalidate()творами, але parent.bringChildToFront(child)ні. Де логіка, яку ми всі очікуємо від ОС?
Олівер Хауслер

Для того, щоб оживити деякі погляди (переклади у X та Y), я спробував кілька комбінацій для LinearLayout, FrameLayout та RelativeLayout, але завжди були проблеми (пов’язані з розмірами, що перекриваються чи не пропорційними). Нарешті android:clipChildren="false"зробив трюк. Дякую!
JCarlosR

15

Зверніть увагу, що ви можете використовувати, view.setZ(float)починаючи з рівня 21 API. Тут ви можете знайти більше інформації.


13

Думав, я би додав відповідь з моменту впровадження

android: перекладZ

Поле XML змінило речі. Інші відповіді, які передбачають біг

childView1.bringToFront();

parentView.invalidate();

на місці ВІДКРИТИ, тому що цей код НЕ буде виводити childView1 перед будь-яким видом із жорстким кодом Android: translationZ у XML-файлі. У мене були проблеми з цим, і як тільки я видалив це поле з інших поглядів, createToFront () спрацював чудово.


це справедливо і для андроїд 5-хelevation
shelll

5

В API 21 є view.setElevation(float)вбудована версія

Використовувати ViewCompat.setElevation(view, float);для зворотної сумісності

Більше методів ViewCompat.setZ(v, pixels)іViewCompat.setTranslationZ(v, pixels)

Інший спосіб збирати кнопки або переглядати масив та використовувати їх addViewдля додавання до RelativeLayout



1

Ви можете використовувати власні RelativeLayoutз переробленими

protected int getChildDrawingOrder (int childCount, int i)

Будьте в курсі - цей метод сприймає парам iяк "який погляд я повинен малювати i'th". Так ViewPagerпрацює. Він встановлює індивідуальний порядок малювання спільно з PageTransformer.


0

Перевірте, чи є у вас висота на одному з представлень у XML. Якщо так, додайте висоту до іншого пункту або видаліть висоту, щоб вирішити проблему. Звідси саме порядок поглядів диктує те, що виходить над іншим.


0

Або помістіть кнопку перекриття або представлення всередині FrameLayout. Тоді RelativeLayout у файлі xml буде дотримуватися порядку дочірнього макета, який вони додавали.


0

Ви також можете використовувати зразок коду нижче, щоб досягти того ж

ViewCompat.setElevation(sourceView, ViewCompat.getElevation(mCardView)+1);

Це сумісність із зворотним ходом. Ось mCardViewподання, яке має бути нижче sourceView.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.