Como colocar / sobrepor (z-index) uma visão acima de outra visão no android


230

Eu tenho um layout linear que consiste em visualização de imagem e visualização de texto, um abaixo do outro em um layout linear.

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

Algumas regras podem estar faltando, isso é para dar uma idéia de como o layout é exibido. Eu quero outra exibição de texto pequena, digamos 50dip de comprimento e largura, colocada sobre a visualização de imagem, por "sobre" eu quis dizer mais o índice z do que a visualização de imagem. Quero colocar isso, no centro e acima (sobreposição) da visualização de imagem.

Quero saber como podemos colocar uma visualização acima da outra, com diferentes índices z (de preferência em layout linear)?

Respostas:


295

Você não pode usar um LinearLayout para isso, mas pode usar um FrameLayout. Em a FrameLayout, o índice z é definido pela ordem em que os itens são adicionados, por exemplo:

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

Nesse caso, o TextView seria desenhado na parte superior do ImageView, na parte inferior central da imagem.


Sim, eu fiz isso usando o próprio layout do quadro depois de passar pela documentação. Obrigado.
— sentou

11
Existe uma vantagem em usar o FrameLayout em vez do RelativeLayout para isso?
— Ixx

12
O FrameLayout não se relaciona a outras visualizações no grupo, apenas as coloca em camadas em relação ao pai. RelativeLayout é mais para posicionamento em relação a outros itens.
— 22412 Kevin Coppock

3
Oi kcoppock meu celular (hdpi) não respeita a ordem z no layout do quadro, mas eu tenho uma outra (xhdpi) e respeito essa ordem, você sabe por que fazer isso? Desde já, obrigado! : D
— Merlí Escarpenter Pérez

1
A partir da API 21 / KitKat, agora você pode usar setZ e translationZ; o hack FrameLayout não é mais necessário (finalmente!). Esta deve ser a resposta preferida para desenvolvimento 5.0+ moderna: stackoverflow.com/a/29703860/358578
— pbarranis

183

3
também podemos usar isso em arquivos xml?
— Anúncios

2
Eu estava procurando algo para trazer minha visão para alterar o itz zindex durante a animação de tradução.
— DeltaCap019 25/10

Você poderia encontrar uma solução para animação de tradução?
— NAkhmedov 15/09/14

9
bringChildToFront () apenas muda o índice de modo de exibição dentro do seu pai
— Zar E Ahmer

4
esta parafusos toda a ordem de layout
— Jemshit Iskenderov

66

RelativeLayout funciona da mesma maneira, a última imagem no layout relativo vence.


14
A menos que você use a elevação, também precisará do maior valor.
— Sami Kuhmonen

5
Esta pergunta foi feita e respondida antes da elevação existir. O uso da elevação não corrigirá o problema se o seu aplicativo tiver um minSdk menor que o Lollipop (em telefones pré-pirulito, o layout parecerá errado se você confiar apenas na elevação) - você ainda precisará prestar atenção à ordem do layout. Você está certo, porém, de que se usar elevação no componente inferior - você definitivamente precisa ter pelo menos o mesmo ou mais alto no topo.
— Jt-gilkeson

27

Alterando a ordem do sorteio

Uma alternativa é alterar a ordem em que as vistas são desenhadas pelo pai. Você pode ativar esse recurso no ViewGroup chamando setChildrenDrawingOrderEnabled (true) e substituindo getChildDrawingOrder (int childCount, int i) .

Exemplo:

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

Resultado:

Ligar OrderLayout#setDrawOrder(int)com 0-1-2 resulta em:

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui


Você chama setDrawOrder (i) no onCreate () da atividade? Se eu tiver 6 widgets no meu xml, preciso inicializar cada linha de DRAW_ORDERS com uma matriz de 6 números (0-5)?
— John Ward

@JohnWard O layout mostrado acima é apenas para fins de exemplo, você pode definir seu próprio comportamento em getChildDrawingOrder ().
— Tobrun 22/01/19

aqui está post relacionado com a quantidade de código claro: stackoverflow.com/questions/20524162/framelayout-in-reverse
— Robert

20

Você pode usar a view.setZ(float)partir do nível 21. da API. Aqui você pode encontrar mais informações.


3
Agora, essa deve ser a resposta preferida para a API 21 / KitKat / 5.0 ou superior. Felizmente, o antigo frameLayout hack não é mais necessário. Pessoalmente, não entendo a diferença entre setZ e translationZ, mas o último é um atributo e funcionou lindamente para mim. Obrigado!
— Pbarranis

Para as APIs anteriores, você também pode usar o ViewCompat # setZ ().
— Ali Yucel Akgul 04/10

@AliYucelAkgul se você olhar os documentos aqui , pode ver Compatibility: API < 21: No-op . Então eu acho que não vai funcionar
— Vadim Kotov

@VadimKotov, eu tentei no meu aplicativo e ele simplesmente funciona.
— Ali Yucel Akgul 04/10

@AliYucelAkgul bem, isso é estranho. Talvez um erro na documentação? Você tem 100% de certeza de que está funcionando para a API <21? Eu tenho uma idéia que pode mudar a ordem de pontos de vista para as APIs anteriores, mas não coisas extravagantes como elevação, etc ..
— Vadim Kotov

14

Resolvi o mesmo problema adicionando android:elevation="1dp"a qual visualização você deseja sobre outra. Mas ele não pode ser exibido abaixo de 5.0 e terá uma pequena sombra; se você puder aceitá-lo, tudo bem.

Então, disse a solução mais correta que é @kcoppock.


7

Tente isso em um RelativeLayout:

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

Funciona para mim.


2
Você deveria explicar um pouco melhor. Por exemplo, onde você colocaria esse código?
— #

Bem, eu coloquei no método OnCreate (). Cada imagem adicionada possui um índice z de preferência sobre as adicionadas anteriormente. Quero dizer, através do índice z, posso mudar a posição do próximo atrás do anterior.
— Rizzo

5

Existe uma maneira de usar o LinearLayout. Apenas defina o marginTop do seu elemento anterior com o valor negativo correspondente e verifique se o elemento que você deseja no topo está após o elemento que você deseja abaixo em seu 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

Como você não pode fazê-lo com layouts lineares, terá que optar por um RelativeLayout .


RelativeLayout não estende frameLayout, você tem certeza de que funcionará?
— ekatz

Será. Você pode usar qualquer um dos FrameLayout ou RelativeLayout. Cada um com maneiras diferentes de colocar vistas filho. Consulte os documentos para saber mais sobre esses layouts.
— Vincent Mimoun-Prat

este é o caminho a percorrer
— Albert James Teddy

0

Se você estiver adicionando o modo de exibição programaticamente, poderá usar yourLayout.addView(view, 1);

onde 1 is the index.


0

Eu uso isso, se você deseja que apenas uma visualização seja apresentada quando necessário:

containerView.bringChildToFront(topView);

containerView é o container de visualizações a serem classificadas, topView é a view que eu quero ter como a mais alta no container.

para que várias visualizações sejam organizadas, está prestes a usar setChildrenDrawingOrderEnabled (true) e substituindo getChildDrawingOrder (int childCount, int i) conforme mencionado acima.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.