Perché LayoutInflater ignora i parametri layout_width e layout_height che ho specificato?


168

Ho avuto grossi problemi a far funzionare LayoutInflater come previsto, e così hanno fatto altre persone: Come utilizzare layoutinflator per aggiungere visualizzazioni in fase di esecuzione? .

Perché LayoutInflater ignora i parametri di layout che ho specificato? Ad esempio, perché i valori layout_widthe layout_heightdelle mie risorse XML non vengono rispettati?


È vero - mi fa male o ho scelto il posto sbagliato? Ho pensato di condividere i miei risultati. Devo ammettere che i tutorial non sono specificamente menzionati nella pagina delle domande frequenti.
Andig

3
vedi l'ultimo paragrafo della prima domanda nella faq. pubblicarlo come una domanda e quindi pubblicare il tutorial come risposta. ovviamente, puoi modificare questa domanda tagliando e incollando il tutorial nella risposta. Valuterò se risolverai questo problema.
pietre preziose,

Risposte:


381

Ho studiato questo problema, facendo riferimento ai documenti LayoutInflater e impostando un piccolo progetto dimostrativo di esempio. Le esercitazioni seguenti mostrano come popolare dinamicamente un layout usando LayoutInflater.

Prima di iniziare, guarda quali sono i LayoutInflater.inflate()parametri:

  • risorsa : ID per caricare una risorsa di layout XML (ad es. R.layout.main_page)
  • root : vista facoltativa per essere il genitore della gerarchia generata (if attachToRootis true), oppure semplicemente un oggetto che fornisce un set di LayoutParamsvalori per root della gerarchia restituita (if attachToRootis false.)
  • attachToRoot : se la gerarchia inflazionata deve essere collegata al parametro root? Se false, root viene utilizzato solo per creare la sottoclasse corretta di LayoutParamsper la vista root nell'XML.

  • Restituisce : la vista radice della gerarchia gonfiata. Se root è stato fornito ed attachToRootè true, questo è root; altrimenti è la radice del file XML gonfiato.

Ora per il layout e il codice di esempio.

Layout principale ( main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

In questo contenitore è aggiunto un TextView separato, visibile come un piccolo quadrato rosso se i parametri di layout vengono applicati correttamente da XML ( red.xml):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:background="#ff0000"
    android:text="red" />

Ora LayoutInflaterviene utilizzato con diverse varianti dei parametri di chiamata

public class InflaterTest extends Activity {

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);
      ViewGroup parent = (ViewGroup) findViewById(R.id.container);

      // result: layout_height=wrap_content layout_width=match_parent
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view);

      // result: layout_height=100 layout_width=100
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view, 100, 100);

      // result: layout_height=25dp layout_width=25dp
      // view=textView due to attachRoot=false
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, false);
      parent.addView(view);

      // result: layout_height=25dp layout_width=25dp 
      // parent.addView not necessary as this is already done by attachRoot=true
      // view=root due to parent supplied as hierarchy root and attachRoot=true
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, true);
    }
}

I risultati effettivi delle variazioni dei parametri sono documentati nel codice.

SINOSSI: la chiamata LayoutInflatersenza specificare root porta a gonfiare la chiamata ignorando i parametri di layout dall'XML. La chiamata si gonfia con root non è uguale nulle attachRoot=truecarica i parametri di layout, ma restituisce nuovamente l'oggetto root, il che impedisce ulteriori modifiche al layout dell'oggetto caricato (a meno che non sia possibile trovarlo utilizzando findViewById()). La convenzione di chiamata che molto probabilmente vorresti usare è quindi questa:

loadedView = LayoutInflater.from(context)
                .inflate(R.layout.layout_to_load, parent, false);

Per aiutare con problemi di layout, si consiglia vivamente Layout Inspector .


20
Risposta eccellente. Ho lavorato su Android per 3 anni e contando e avevo ancora qualcosa da imparare da questo.
Reuben Scratton,

Ciao, c'è un modo per fare la stessa cosa con il codice java invece di gonfiare con R.layout. perché non ho layout. Ho creato la vista con il codice Java e voglio aggiungere la stessa vista per 300 volte.
Raj

1
@andig: Activityè una sottoclasse di Contexte gli esempi della risposta sono nell'ambito di Activity, quindi per semplificare ho sostituito getBaseContext()con thiscome, per il bene di questa risposta, è equivalente.
Marcin Orlowski,

5
il contenitore ha layout_width e layout_height impostati su "match_parent"; quindi il commento dice "// risultato: layout_height = wrap_content layout_width = match_parent". Mi sto perdendo sth?
Marian Paździoch

1
Grazie per fare la ricerca e condividere i risultati! Inoltre, rispondo alla domanda di Marian.
LarsH,

5

andig ha ragione nel dire che un motivo comune per LayoutInflater che ignora layout_params sarebbe perché non è stata specificata una radice. Molte persone pensano che puoi passare a null per root. Questo è accettabile per alcuni scenari come una finestra di dialogo, in cui non si ha accesso a root al momento della creazione. Una buona regola da seguire, tuttavia, è che se si dispone di root, assegnarlo a LayoutInflater.

Ho scritto un post sul blog approfondito su questo che puoi controllare qui:

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/


1
This is acceptable for a few scenarios such as a dialogera tutto ciò di cui avevo bisogno
debuttante Developer,

0

voglio aggiungere alla risposta principale sopra
ho provato a seguirlo ma il mio recyclerView ha iniziato ad allungare ogni oggetto su uno schermo che
ho dovuto aggiungere alla riga successiva dopo aver gonfiato per raggiungere l'obiettivo

itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));

Ho già aggiunto questi parametri con xml ma non ha funzionato correttamente
e con questa linea è tutto ok

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.