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);
}
MickeyR
fonte
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.
Aleadam
fonte
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();

surfista de teclado
fonte
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.

Mohanad ALKHOULI
fonte
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);
}
Namaded Ahmad
fonte
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

jkincali
fonte
9

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

ViewGroup vg = (ViewGroup) findViewById (R.id.videoTitleTxtView);
 vg.removeAllViews();
 vg.refreshDrawableState();
Datta Kunde
fonte
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();
}
Farhan
fonte
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));
}
Krilivye
fonte
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.

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

user3612162
fonte
2

Este parece ser um bug conhecido .

Ben Williams
fonte
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.

Cai
fonte
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);
sivaBE35
fonte
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()
Jack '
fonte
0

Tente isto

view.requestLayout();
Milind Chaudhary
fonte
-1

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

setContentView(R.layout.mainscreen);
Krzysztof Tkacz
fonte
-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));
Anshul Aggarwal
fonte
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