Come forzare un intero layout Visualizza aggiornamento?


173

Voglio forzare la vista delle risorse del layout principale per ridisegnare / aggiornare, ad esempio il metodo Activity.onResume (). Come posso fare questo ?

Per vista layout principale, intendo quello ('R.layout.mainscreen' di seguito) che viene chiamato nel mio Activity.onCreate (), in questo modo: -

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

Hai provato a nominare il tuo Linear / Relative / whateverLayout, chiamando findViewById su di esso e quindi chiamando invalidate () su quello? (Lo metterei come una risposta, ma non so se i genitori invalidanti invalidano anche i bambini e non sono un posto dove posso provarlo.)
Ben Williams,

Grazie anche a ! Sto ancora lottando con questo però. Puoi dare un'occhiata a quello che ho pubblicato di seguito. Ho bisogno di questo codice (o altro?) Per far aggiornare il mio tema ...
MickeyR

Risposte:


149

Per rispondere rigorosamente alla domanda: utilizzare invalidate ():

public void invalidate () Da: API Livello 1

Invalida l'intera vista. Se la vista è visibile, onDraw (Canvas) verrà chiamato in futuro. Questo deve essere chiamato da un thread dell'interfaccia utente. Per chiamare da un thread non UI, chiama postInvalidate ().

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

Ora, quando l'attività riprende, ogni vista si disegna da sola. Non è necessario chiamare per invalidare (). Per applicare il tema, assicurati di farlo prima che venga disegnata qualsiasi vista, ovvero primasetContentView(R.layout.mainscreen);

public void setTheme (int resid) Da: API Livello 1

Imposta il tema di base per questo contesto. Si noti che questo dovrebbe essere chiamato prima di istanziare qualsiasi vista nel contesto (ad esempio prima di chiamare setContentView (View) o infllate (int, ViewGroup)).

Il riferimento al documento API è qui: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

Poiché il metodo onDraw () funziona su viste già istanziate, setTheme non funzionerà. Non ho esperienza con i temi, ma due opzioni alternative che posso pensare sono:

  1. chiama setTheme in onCreate () invece, o
  2. ripetere setContentView (R.layout.mainscreen); per forzare a reintegrare tutto il layout.

Grazie ! Funziona bene, ma non vedo cosa mi aspettassi. Appena prima di eseguire il tuo codice, eseguo Activity.setTheme (newtheme) ma questa chiamata invalidate () non fa cambiare il tema (es. Da Dark a Light). Invalidate () dovrebbe essere in grado di farlo?
MickeyR,

@MickeyR no, non dovrebbe. Controlla la mia risposta aggiornata. Se queste due opzioni non funzionano, dovrai riavviare la tua attività.
Aleadam,

L'opzione (1) funziona. La mia app inizierà con il tema corretto, ma se la cambio durante l'esecuzione, devo riavviare la mia app in modo che onCreate () venga richiamato di nuovo.
MickeyR,

L'opzione (2) è la strada che volevo prendere. Quindi, quando il tema viene cambiato durante l'esecuzione, volevo che OnRestart () facesse questo: - setTheme (getPreferenceTheme ()); e setContentView (R.layout.main); Ma questo non cambia il mio tema. Non riesco a far funzionare questa seconda opzione ...?!
Topolino

Ho capito che per far funzionare l'opzione (2) ho bisogno di "ri-gonfiare la gerarchia della vista". Ho provato diverse cose per raggiungere questo obiettivo, ma non sono davvero sicuro di cosa significhi né come farlo.
MickeyR,

41

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


3
Grazie ! Stessa risposta che ho postato sopra ad Aleadam. Questo invalidate () non provoca l'aggiornamento del tema dell'attività, che è ciò di cui ho bisogno.
MickeyR,

36

Provalo recreate()farà ricreare questa attività.


4
Ho provato tutte le opzioni in questo thread, e questo è l'unico che ha funzionato con gli effetti collaterali meno indesiderati.
swooby

1
E se avessi bisogno di fare questo con il onResumemetodo. Questo mi dà un ciclo infinito: /
Kamil Witkowski il

Beh, non consiglio di usarlo fino a quando non ne avrai davvero bisogno. È possibile salvare alcuni flag nelle preferenze condivise per evitare il ciclo infinito.
Mohanad ALKHOULI,

funziona ma non consiglierei di usarlo nella vera modalità di produzione app. Ne avevo bisogno solo per la modalità debug, quindi l'effetto collaterale dell'intero aggiornamento dell'interfaccia utente non è critico.
drorsun,

31

Soluzione:

Ragazzi, ho provato tutte le vostre soluzioni ma non hanno funzionato per me, devo impostare setVisibility of EditText su VISIBLE e questo EditText dovrebbe essere visibile quindi su ScrollView , ma non sono riuscito ad aggiornare la vista di root per rendere effettive. Ho risolto il mio problema, quando ho bisogno di aggiornare la vista, quindi ho cambiato la visibilità di ScrollView su GONE e poi l'ho impostato di nuovo su VISIBLE per avere effetto e ha funzionato per me. Questa non è la soluzione esatta ma ha funzionato solo.

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

2
@MickeyR Per favore, accetta una risposta, così la gente può trovare facilmente la soluzione
Naveed Ahmad,

wow .. ho anche provato tutti i sollutions proposti ma questo sembra essere l'unico a funzionare, ma è un po 'orribile ...
Rik van Velzen

Non so perché @MickeyR non accetta questa risposta
Naveed Ahmad,

1
@NaveedAhmad Grazie! Dopo 4 ore di lavoro, questa è stata l'unica soluzione che ha funzionato.
Codelicious

10

Chiamare invalidate()o postInvalidate()sul layout di root apparentemente NON garantisce che le viste dei bambini verranno ridisegnate. Nel mio caso specifico, il mio layout di root era un TableLayout e aveva diversi figli della classe TableRow e TextView. Chiamata postInvalidate(), o requestLayout()o anche forceLayout()sulla radice oggetto TableLayout non ha causato alcun TextViews nel layout di essere riemessa.

Quindi, quello che ho finito è stato analizzare in modo ricorsivo il layout alla ricerca di quelle TextView e quindi invocare postInvalidate()ciascuno di quegli oggetti TextView.

Il codice è disponibile su GitHub: https://github.com/jkincali/Android-LinearLayout-Parser


9

Altrimenti puoi provare anche questo-

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

4
Grazie per questo ! Ma questo ha rimosso tutte le viste che avevo (TextView, Pulsanti ecc.) Ma non le ha ridisegnate - il mio schermo è rimasto vuoto ...
MickeyR

è necessario aggiornare correttamente la vista, quindi è necessario chiamare nuovamente la funzione di disegno. dopo aver pulito la vista precedente.
Datta Kunde,

4

Basta impostare la visualizzazione del contenuto su onresume

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

Esempio:

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

Ciao, ho provato questo e gli stessi dati nella lista sono stati estratti due volte, quindi se avessi 4 righe e l'aggiornamento avrebbe dovuto aggiungere una quinta riga, invece finirò con 10, quindi 15, ... cosa fare?
iOSAndroidWindowsMobileAppsDev

4

Prova questa soluzione alternativa per il problema del 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);

Ciò ti consente di ricaricare con modifiche al tema e nasconde le animazioni.


3

Stavo riscontrando anche questo problema, ma seguendo l'esempio di Farhan sull'uso setContentView()ho fatto proprio questo. l'utilizzo setContentView()da solo non è stato tuttavia sufficiente. Ho scoperto che dovevo ripopolare tutte le mie opinioni con informazioni. Per risolvere questo problema, ho appena estratto tutto quel codice in un altro metodo (l'ho chiamato build) e nel mio onCreatemetodo ho semplicemente chiamato quella build. Ora, ogni volta che si verifica il mio evento, voglio che la mia attività si "aggiorni", chiamo solo build, gli do le nuove informazioni (che passo come parametri da costruire) e ho un'attività aggiornata.


2

Questo sembra essere un bug noto .


setTheme funziona quando riavvio la mia attività (call finish () e quindi startActivity ()). Non riesco proprio a farlo aggiornare il tema senza riavviare la mia attività ...
MickeyR

0

Non so se questo è sicuro o no, ma ha funzionato per me. I kinda imbattuto in questo problema io stesso e ho cercato invalidate()e requestLayout()ma senza alcun risultato. Quindi ho appena chiamato di onCreate(null)nuovo tutto e ha funzionato. Se questo non è sicuro, per favore fatemelo sapere. Spero che questo aiuti qualcuno là fuori.


Stai impostando saveInstanceState su null che potrebbe causare comportamenti imprevisti. Per maggiori informazioni: stackoverflow.com/questions/15115975/...
PhilipB

0

Ecco come ho usato per aggiornare il mio 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

Per cancellare una vista che estende ViewGroup, devi solo usare il metodo removeAllViews()

Proprio così (se hai un ViewGroup chiamato myElement):

myElement.removeAllViews()


-1

Non sono sicuro che sia un buon approccio, ma lo chiamo solo ogni volta:

setContentView(R.layout.mainscreen);

-8

Richiama l'attività stessa usando l'intento. Ad esempio per aggiornare il layout di MainActivity, procedere come segue:

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

2
È brutto! Quando lo fai, aggiungi semplicemente una nuova attività in pila, quindi, quando premi il pulsante indietro, tornerai alla stessa attività.
Daniel Beltrami,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.