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.