Como forçar um layout inteiro Exibir atualização?


173

Quero forçar a exibição principal do recurso de layout para redesenhar / atualizar, digamos o método Activity.onResume (). Como posso fazer isso ?

Na exibição principal do layout, quero dizer a ('R.layout.mainscreen' abaixo) que é chamada em minha Activity.onCreate (), assim: -

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainscreen);
}

Você já tentou nomear seu Linear / Relative / WhateverLayout anexo, chamando findViewById e, em seguida, chama invalidate ()? (Eu ia colocar isso como uma resposta, mas eu não sei se os pais invalidando também invalida as crianças e eu não estou em algum lugar que eu possa testá-lo.)
Ben Williams

Obrigado também! Ainda estou lutando com isso. Você pode dar uma olhada no que eu publiquei abaixo. Eu preciso este código para fazer com que o meu tema para refrescar ... (ou outra?)
MickeyR

Respostas:


149

Para responder estritamente à pergunta: Use invalidate ():

invalid público inválido () desde: API nível 1

Invalide a exibição inteira. Se a vista estiver visível, o onDraw (Canvas) será chamado em algum momento no futuro. Isso deve ser chamado de um thread da interface do usuário. Para chamar de um thread que não seja da interface do usuário, chame postInvalidate ().

ViewGroup vg = findViewById (R.id.mainLayout);
vg.invalidate();

Agora, quando a Atividade é retomada, faz com que cada Visualização se desenhe. Nenhuma chamada para invalidar () deve ser necessária. Para aplicar o tema, faça-o antes de desenhar qualquer Visualização, ou seja, antes desetContentView(R.layout.mainscreen);

public void setTheme (int resid) Desde: API nível 1

Defina o tema base para este contexto. Observe que isso deve ser chamado antes que quaisquer visualizações sejam instanciadas no contexto (por exemplo, antes de chamar setContentView (View) ou inflar (int, ViewGroup)).

A referência do documento da API está aqui: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

Como o método onDraw () funciona em Views já instanciadas, setTheme não funcionará. Eu não tenho experiência com temas, mas duas opções alternativas que posso pensar são:

  1. chame setTheme em onCreate () ou
  2. refazer setContentView (R.layout.mainscreen); para forçar o restabelecimento de todo o layout.

Obrigado ! Isso funciona bem, mas não vejo o que esperava. Antes de executar seu código, eu corro Activity.setTheme (newtheme), mas essa chamada invalidate () não faz com que o tema seja alterado (por exemplo, de Dark para Light). Invalidate () deve ser capaz de fazer isso?
MickeyR

@MickeyR não, não deveria. Verifique minha resposta atualizada. Se essas duas opções não funcionarem, você precisará reiniciar sua Atividade.
Aleadam 13/05/11

A opção (1) funciona. Meu aplicativo iniciará com o tema correto, mas se eu o alterar durante a execução, será necessário reiniciar o aplicativo para que onCreate () seja chamado novamente.
MickeyR

A opção (2) é o caminho que eu queria seguir. Portanto, quando o tema é alterado durante a execução, eu queria que o onRestart () fizesse o seguinte: - setTheme (getPreferenceTheme ()); e setContentView (R.layout.main); Mas isso não muda meu tema. Não consigo fazer com que esta segunda opção funcione ...?!
MickeyR

Entendi que, para que a opção (2) funcione, preciso "inflar novamente a hierarquia de visualizações". Eu tentei coisas diferentes para conseguir isso, mas não tenho muita certeza do que isso significa nem como fazer isso.
MickeyR

41

Experimentar getWindow().getDecorView().findViewById(android.R.id.content).invalidate();


3
Obrigado ! A mesma resposta que eu postei acima para Aleadam. Isso invalidate () não faz com que o tema da atividade seja atualizado, é o que eu preciso.
MickeyR

36

Experimente recreate()fazer com que esta atividade seja recriada.


4
Eu tentei todas as opções neste segmento, e este é o único que funcionou com os efeitos colaterais menos indesejados.
swooby

1
E se eu precisar disso no onResumemétodo. Isso me dá um loop infinito: /
Kamil Witkowski

Bem, eu não recomendo usá-lo até que você realmente precise. Você pode salvar alguns sinalizadores nas preferências compartilhadas para evitar o loop infinito.
Mohanad ALKHOULI

isso funciona, mas eu não recomendaria usá-lo no aplicativo de modo de produção real. Eu só precisava dele no modo de depuração para que o efeito colateral de toda a atualização da interface do usuário não seja crítico.
drorsun

31

Solução:

Pessoal, tentei todas as suas soluções, mas elas não funcionaram para mim, tenho que definir setVisibility of EditText como VISIBLE e esse EditText deve ficar visível no ScrollView , mas não consegui atualizar a visualização raiz para entrar em vigor. Resolvi meu problema, quando preciso atualizar a exibição, alterei a visibilidade do ScrollView para GONE e, em seguida, defina-a como VISIBLE para entrar em vigor e funcionou para mim. Esta não é a solução exata, mas apenas funcionou.

 private void refreshView(){
    mScrollView.setVisibility(View.GONE);
    mScrollView.setVisibility(View.VISIBLE);
}

2
@MickeyR Por favor, aceite uma resposta, que as pessoas possam encontrar a solução facilmente
Naveed Ahmad

wow .. Eu também tentei todos os sollutions propostas, mas este parece ser o único trabalho, mas é uma espécie de horrível ...
Rik van Velzen

Eu não sei porque @MickeyR não está aceitando esta resposta
Naveed Ahmad

1
@NaveedAhmad Thank you! Depois de 4 horas fazendo tudo o que pude, essa foi a única solução que funcionou.
Codelicious

10

Aparentemente, chamar invalidate()ou postInvalidate()no layout raiz NÃO garante que as visualizações de crianças sejam redesenhadas. No meu caso específico, meu layout raiz era um TableLayout e tinha vários filhos da classe TableRow e TextView. Chamando postInvalidate(), ou requestLayout()ou mesmo forceLayout()na raiz TableLayout objeto não causou quaisquer TextViews no layout a ser redesenhado.

Então, o que acabei fazendo foi analisar recursivamente o layout procurando por esses TextViews e, em seguida, chamando postInvalidate()cada um desses objetos TextView.

O código pode ser encontrado no GitHub: https://github.com/jkincali/Android-LinearLayout-Parser


9

Caso contrário, você pode tentar isso também-

ViewGroup vg = (ViewGroup) findViewById (R.id.videoTitleTxtView);
 vg.removeAllViews();
 vg.refreshDrawableState();

4
Obrigado por isso! Mas, este removidas todas as visões que tive (TextView, botões etc), mas não re-desenhar-los - minha tela permaneceu em branco ...
MickeyR

você precisa atualizar sua visualização corretamente e chamar a função draw novamente. depois de limpar a vista anterior.
Datta Kunde

4

Basta definir a visualização do conteúdo em um resumo

setContentView (R.layout.yourview) dentro de onResume ..

Exemplo:

@Override
public void onResume(){
super.onResume();
setContentView(R.layout.activity_main); 
postIncomeTotals();
}

Oi Eu tentei isso e os mesmos dados no listview são puxados duas vezes, portanto, se eu tivesse 4 linhas e a atualização deveria adicionar uma quinta linha, em vez disso, terminarei com 10 e 15, ... o que fazer?
iOSAndroidWindowsMobileAppsDev

4

Tente esta solução alternativa para o problema de tema:

@Override
public void onBackPressed() {
    NavUtils.navigateUpTo(this, new Intent(this,
            MyNeedToBeRefreshed.class));
}

3
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);

Isso permite que você recarregue com alterações de tema e oculte as animações.


3

Eu estava tendo esse problema também, mas seguindo o exemplo de Farhan, setContentView()fiz exatamente isso. usar setContentView()por si só não era suficiente. Eu descobri que tinha que repovoar todas as minhas opiniões com informações. Para consertar isso, eu apenas puxei todo esse código para outro método (eu o chamei de build) e no meu onCreatemétodo eu chamo de build. Agora, sempre que ocorrer meu evento, que desejo que minha atividade seja "atualizada", chamo apenas de compilação, forneça as novas informações (que passo como parâmetros para compilar) e tenho uma atividade atualizada.


2

Este parece ser um bug conhecido .


O setTheme funciona é encontrado quando eu reinicio minha atividade (chamada finish () e startActivity ()). Eu apenas não posso obtê-lo para atualizar o tema sem reiniciar minha atividade ...
MickeyR

0

Não sei se isso é seguro ou não, mas funcionou para mim. Eu meio que corri para este problema sozinho e tentou invalidate()e requestLayout(), mas sem sucesso. Então eu liguei para o meu onCreate(null)tudo de novo e funcionou. Se isso não for seguro, entre em contato. Espero que isto seja útil a alguém.


Você está configurando o SavedInstanceState como nulo, o que pode causar um comportamento inesperado. Para obter mais informações: stackoverflow.com/questions/15115975/…
PhilipB

0

É assim que eu costumava atualizar meu layout

Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);

0

Para limpar uma exibição que estende o ViewGroup, você só precisa usar o método removeAllViews()

Assim (se você tiver um ViewGroup chamado myElement):

myElement.removeAllViews()


-1

Não tenho certeza se é uma boa abordagem, mas eu ligo sempre assim:

setContentView(R.layout.mainscreen);

-8

Apenas chame a atividade novamente usando a intenção. Por exemplo, para atualizar o layout de MainActivity, faça o seguinte:

startActivity(new Intent(MainActivity.this, MainActivity.class));

2
Isso é feio! Ao fazer isso, basta adicionar uma nova atividade na pilha; assim, quando você pressionar o botão Voltar, retornará à mesma atividade.
Daniel Beltrami
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.