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

Lukap
fonte
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();
Medo Elkamaly
fonte
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

shrewdu
fonte
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=""
Toby
fonte
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!

Justin
fonte
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
25

Com esse código em xml

 android:translationZ="90dp"
Krishna
fonte
3
De onde 90dpveio?
Sudhir Khanger 15/07/19
1
é entrada manual. Você pode tentar com base em sua exigência. quer 45dp ou 135dp ou 180dp ou 270DP
Krishna
Você não poderia simplesmente usar 1DP?
Tyler Turnbull
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.

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

Fajar Ulin Nuha
fonte
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.

asozcan
fonte
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=""
Mudassir Khan
fonte
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}"/>
Ahmad Aghazadeh
fonte
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

Ranjit Mishra
fonte
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.

Cristian
fonte
0

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

Amitoj
fonte
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!

PYK
fonte
-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.

Shuvendu Dhal
fonte
-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);
thenosic
fonte
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