Como trazer a visão na frente de tudo?


130

Eu tenho atividade e muitos widgets, alguns deles têm animações e, devido às animações, alguns dos widgets estão se movendo (traduzindo) um sobre o outro. Por exemplo, a exibição de texto está se movendo sobre alguns botões. . .

Agora, quero que os botões estejam sempre na frente. E quando a visualização de texto estiver em movimento, quero passar por trás dos botões.

Não consigo fazer isso, tentei tudo o que sei e "bringToFront ()" definitivamente não funciona.

note Observação: não quero controlar a ordem z pela ordem de colocação do elemento no layout, porque simplesmente não posso :), o layout é complexo e não consigo colocar todos os botões no início do layout


3
Eu usei um RelativeLayoutcom a exibição "top" aparecendo por último no XML. Veja stackoverflow.com/a/31340762/1121497
— Ferran Maylinch

Alguém pode dizer código correspondente no xml de 'BringToFront'
— Shirish Herwade

Tente usar a elevação bottomView = elevação: 1dp e topView = elevação: 2dp no seu xml || ViewCompat.setElevation (Exibir, int)
— Tlacaelel Ramon Luis 10 /

Respostas:


144

Você pode chamar bringToFront () na exibição que deseja exibir na frente

Isto é um exemplo:

    yourView.bringToFront();

4
Resultado inesperado: usei isso em um layout linear vertical e a vista trazida para a frente apareceu na parte inferior ... Por exemplo, eu tinha A / B / Ce queria trazer Apara a frente, então, depois de executar a.bringToFront(), acabei com um layout como B / C / A.
— Ferran Maylinch

2
Então eu descobri LinearLayoutque não pode ser usado com bringToFront. Acabei usando um RelativeLayout. Veja meu comentário sobre a pergunta em si.
— Ferran Maylinch

1
Alguém pode dizer código correspondente no xml de 'BringToFront'
— Shirish Herwade

Isso resulta no reposicionamento do elemento que estou movendo para a frente por qualquer motivo. ViewCompat.setTranslationZ(view, 1)funciona perfeitamente, por outro lado.
— Bimde

1
se eu usei no manifesto android: theme = "@ android: style / Theme.Light.NoTitleBar" em atividade que yourView.bringToFront (); funciona perfeitamente, mas eu usei android: theme = "@ android: style / Theme.AppCompat.Light.NoActionBar" yourView.bringToFront (); não funciona Qualquer pista sobre isso.
— Rahul

42

Eu estive pesquisando o estouro de pilha para encontrar uma boa resposta e, quando não consegui encontrar uma, procurei os documentos.

ninguém parece ter tropeçado nessa resposta simples ainda:

ViewCompat.setTranslationZ(view, translationZ);

a tradução padrão z é 0,0


Essa é a posição do elemento no eixo Z em px, também conhecido como elevação. setTranslationX moveria a vista ao longo do eixo X (esquerda / direita), setTranslationY ao longo do eixo Y (superior / inferior). O eixo Z é o terceiro eixo.
— Xdevs23 22/03

Que tal setZ()? Se bem me lembro, a posição Z da vista é sua elevação mais sua translação Z, afinal.
— precisa

2
@ Gensoukyou1337, ViewCompat.setZ(view, yourValueInPixels); view.setZ()funciona apenas na API 21 e superior.
— Johnny Cinco

1
Código Java 8 verificado no Android Studio - ele verifica apenas se SDK_INT> = 21, portanto, para <21 api, não tem efeito.
— Vadim

32

Uma solução ainda mais simples é editar o XML da atividade. Usar

android:translationZ=""

3
Isso é útil apenas na API Android 21 ou superior.
— Isakbob 31/07/19

25

bringToFront()é o caminho certo, mas NOTE que você deve chamar bringToFront()e invalidate()método na visualização de nível mais alto (na visualização raiz), por exemplo:

A hierarquia da sua visualização é:

-RelativeLayout
|--LinearLayout1
|------Button1
|------Button2
|------Button3
|--ImageView
|--LinearLayout2
|------Button4
|------Button5
|------Button6

Portanto, quando você animar seus botões (1 a 6), seus botões estarão abaixo (abaixo) de ImageView. Para trazê-lo (acima), ImageViewvocê deve chamar bringToFront()e invalidate()método em seu LinearLayouts. Então, ele funcionará :) ** NOTA: Lembre-se de definir android:clipChildren="false"o layout raiz ou o gradparent_layout da animação-view. Vamos dar uma olhada no meu código real:

.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hw="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/common_theme_color"
    android:orientation="vertical" >

    <com.binh.helloworld.customviews.HWActionBar
        android:id="@+id/action_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dimen_actionbar_height"
        android:layout_alignParentTop="true"
        hw:titleText="@string/app_name" >
    </com.binh.helloworld.customviews.HWActionBar>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/action_bar"
        android:clipChildren="false" >

        <LinearLayout
            android:id="@+id/layout_top"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>

        <ImageView
            android:id="@+id/imgv_main"
            android:layout_width="@dimen/common_imgv_height"
            android:layout_height="@dimen/common_imgv_height"
            android:layout_centerInParent="true"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>
    </RelativeLayout>

</RelativeLayout>

Algum código em .java

private LinearLayout layoutTop, layoutBottom;
...
layoutTop = (LinearLayout) rootView.findViewById(R.id.layout_top);
layoutBottom = (LinearLayout) rootView.findViewById(R.id.layout_bottom);
...
//when animate back
//dragedView is my layoutTop's child view (i added programmatically) (like buttons in above example) 
dragedView.setVisibility(View.GONE);
layoutTop.bringToFront();
layoutTop.invalidate();
dragedView.startAnimation(animation); // TranslateAnimation
dragedView.setVisibility(View.VISIBLE);

GLuck!


e se você quiser colocar o botão 6 acima da visualização de imagem e não os outros botões?
— Adam Katz

@ AdamKatz: Eu acho que você deve reorganizá-los em outro punho nivelado. Então, traga do seu jeito.
— Justin

obrigado Estou tentando colocar apenas um item de uma exibição de reciclador acima de uma exibição, mas deixamos os outros abaixo, bem presos!
— Adam Katz

Eu usei o mesmo. Está funcionando bem com um único problema que oculta a barra de ferramentas.
— User2980181

Isso funciona com vários níveis? Digamos que eu tenho um ConstraintLayoutque contém um RelativeLayoute outro RelativeLayout, ambos têm o mesmo tamanho que sua raiz ConstraintLayout( match_parent). O primeiro RelativeLayouttem um Buttone também está atrás (em ordem de z) do segundo RelativeLayout. Posso fazer Buttoncom que o primeiro RelativeLayoutapareça como se estivesse em cima de tudo, para que fique visível e clicável usando View::bringToFront()?
— oaskamay 13/07/2018


18

Tente FrameLayout, ele oferece a possibilidade de colocar as visualizações uma acima da outra. Você pode criar dois LinearLayouts: um com vistas de segundo plano e outro com vistas de primeiro plano e combiná-los usando o FrameLayout. Espero que isto ajude.


1
Como podemos colocá-lo no topo como um diálogo?
— Gaurav Arora

@ Infinidade, você pode criar um FragmentDialog para essa finalidade ou simplesmente usar o Theme.Dialog para sua Atividade.
— Egor

Não posso usar o FragmentDialog, pois é incompatível com a API 10. Em segundo lugar, já estou usando um tema para o meu aplicativo. Existe alguma outra maneira? Eu usei o FrameLayout como você disse!
— Gaurav Arora

@ Infinidade, você pode usar a versão da biblioteca de compatibilidade do FragmentDialog, disponível na API 4.
— Egor

8

Se você estiver usando ConstraintLayout, basta colocar o elemento após os outros elementos para torná-lo na frente do que os outros



3

Pode haver outra maneira que salve o dia. Basta iniciar um novo diálogo com o layout desejado e apenas mostrá-lo. Eu preciso dele para mostrar um loadingView sobre um DialogFragment e essa foi a única maneira de obter sucesso.

Dialog topDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar);
topDialog.setContentView(R.layout.dialog_top);
topDialog.show();

bringToFront () pode não funcionar em alguns casos como o meu. Mas o conteúdo do layout dialog_top deve substituir qualquer coisa na camada da interface do usuário. Mas, enfim, essa é uma solução feia.


3

Eu enfrentei o mesmo problema. a seguinte solução funcionou para mim.

 FrameLayout glFrame=(FrameLayout) findViewById(R.id.animatedView);
        glFrame.addView(yourView);
        glFrame.bringToFront();
        glFrame.invalidate();

A segunda solução é usar xml adicionando esse atributo à visualização xml

android:translationZ=""

2

Você pode usar o BindingAdapter assim:

@BindingAdapter("bringToFront")
public static void bringToFront(View view, Boolean flag) {
    if (flag) {
        view.bringToFront();
    }
}


  <ImageView
        ...
        app:bringToFront="@{true}"/>

0

Você precisa usar o framelayout. E a melhor maneira de fazer isso é tornar a visualização invisível quando não forem necessárias. Também é necessário definir a posição para cada vista, para que eles se movam de acordo com a posição correspondente


0

Se você estiver usando um, LinearLayoutdeverá ligar myView.bringToFront()e depois ligar parentView.requestLayout()e parentView.invalidate()forçar o pai a redesenhar com a nova ordem filho.


0

Tente usar a elevação, algo como yourview.setElevation(5);


0

Graças ao usuário do Stack sobre essa explicação, eu tenho esse trabalho mesmo no Android 4.1.1

((View)myView.getParent()).requestLayout();
myView.bringToFront();

No meu uso dinâmico, por exemplo, eu fiz

public void onMyClick(View v)
     {
     ((View)v.getParent()).requestLayout();
     v.bringToFront();
     }

E Bamm!


-2

Organize-os na ordem que você deseja mostrar. Suponha que você queira mostrar a vista 1 na parte superior da vista 2. Em seguida, escreva o código da vista 2 e depois escreva o código da vista 1. Se você não conseguir fazer esse pedido, chame bringToFront () para a visualização raiz do layout que você deseja trazer para a frente.


-32

Você pode definir a visibilidade como falsa em outras visualizações.

view1.setVisibility(View.GONE);
view2.setVisibility(View.GONE);
...

ou

view1.setVisibility(View.INVISIBLE);
view2.setVisibility(View.INVISIBLE);
...

E definir

viewN.setVisibility(View.VISIBLE);

4
Eu preciso que tudo fique visível, esse não é o problema, o problema é a ordem z. se a viabilidade fosse o problema, seria fácil de resolver. . .
— Lukap
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.