2015-05-11 11 views
8

Aggiungo dinamicamente le viste a un layout relativo (diciamo contenitore) in un ciclo for. C'è qualcosa di strano che sto notando.
Quando aggiungo le righe una sotto l'altra in un layout relativo in un ciclo for, Vedo che la prima volta alcune delle viste si sovrappongono. Ma quando blocco e sblocco lo schermo, posso vedere che le viste sono posizionate correttamente.

Dovrei essere a conoscenza di qualcosa quando si aggiungono le viste dinamicamente a un layout relativo?L'aggiunta dinamica di viste in un ciclo for si traduce in un posizionamento casuale - Android

Modifica
ho trovato una soluzione su come sbarazzarsi di questo (si prega di controllare la mia risposta). Ma sarei più che felice di accettare una risposta che analizzi questo problema e mi spieghi perché questo accade.

Ho semplificato il codice e i commenti dovrebbero dare una buona idea di ciò che sto facendo.

int prev_id=ID_OF_THE_ELEMENT_ABOVE; 

/*Empty RelativeView with width and height as MATCH_PARENT and WRAP_CONTENT respectively*/ 
RelativeLayout container=(RelativeLayout) findViewById(R.id.container); 
while(ThereIsData){ 
         /*GET THE DATA HERE THAT HAS TO BE ASSIGNED TO EACH TEXTVIEW*/ 
      ... 


         /* ADD TEXTVIEW #1 below prev_id/ 
      ... 
      ... 

         /*ADD TEXTVIEW #2 (WITH BASELINE OF TEXTVIEW# 
      ... 
      ... 

         /*TEXTVIEW #3 (BELOW TEXTVIEW#1)*/ 
      ... 
      ...        

         /*TEXTVIEW #4 (BELOW TEXTVIEW#2)*/ 
         ... 
      ... 

         /*ASSIGN THE ID OF TEXTVIEW#3 TO prev_id SO THAT 
        IN THE NEXT ITERATION TEXTVIEW#1 CAN USE prev_id 
         */ 
         prev_id=ID(TEXTVIEW#2); 

      /*ADD TEXTVIEWS CREATED IN THIS ITERATION*/ 
      container.addView(TEXTVIEW#1); 
         container.addView(TEXTVIEW#2); 
         container.addView(TEXTVIEW#3); 
         container.addView(TEXTVIEW#4);      
    } 
+0

Tutti gli aggiornamenti sul vostro problema? –

+0

@KirilAleksandrov: ho una soluzione al problema. Puoi pagare la mia risposta. Sto cercando di scoprire perché questo comportamento sta accadendo. Mi hai dato una soluzione, ma sono più interessato a sapere cosa sta succedendo internamente, che sta causando il problema. – Ashwin

risposta

0

Provare ad aggiungere le viste in Layout lineare verticale. seguito collegamento potrebbe aiutare a

http://www.myandroidsolutions.com/2012/06/19/android-layoutinflater-turorial/

gonfiare il layout in ciclo for.

+0

Perché dici così? – Ashwin

+0

Perché usiamo LayoutInflater per aggiungere viste dinamiche e il metodo suggerito è molto facile da implementare. Ho anche utilizzato questo metodo per l'aggiunta dinamica di viste. –

0

Non ho ancora trovato la risposta al motivo per cui questo sta accadendo. Ma ho trovato una soluzione. Dopo aver aggiunto ogni riga nel ciclo, chiama container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); Questo sembra risolvere il problema. Ma penso davvero che container.addView() dovrebbe chiamare anche measure().

/*ADD TEXTVIEWS CREATED IN THIS ITERATION*/ 
      container.addView(TEXTVIEW#1); 
         container.addView(TEXTVIEW#2); 
         container.addView(TEXTVIEW#3); 
         container.addView(TEXTVIEW#4); 
    //--------------------------------------------------------------------- 
        container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); 
+0

Non sono d'accordo. onMeasure è un'operazione che richiede un uso intensivo delle risorse, quindi è consigliabile aggiungere molte visualizzazioni e infine chiamare suMisura alla fine per creare l'interfaccia utente. – DKIT

+0

@DKIT: l'ho provato, aggiungendo tutte le visualizzazioni e quindi chiamando la misura. Ma quello non ha funzionato. Ha funzionato solo quando ho chiamato la misura su ogni iterazione. – Ashwin

+0

Hai provato a chiamare requestLayout e invalidare/postInvalidate nella visualizzazione genitore? – DKIT

4

E 'dovuto al fatto che si stanno avendo un RelativeLayout con height come WRAP_CONTENT, e l'aggiunta di una vista non aggiorna l'intero contenitore in quel momento .. così come avete risposto si può aggiungere un linea a measure le dimensioni esplicitamente o invalidate la vista per ricrearlo completamente.

In ogni caso LinearLayout sarebbe meglio optare per la quanto provvederà automaticamente i bambini in horizontal o vertical modo e si può anche aggiungere la nuova vista in qualsiasi luogo diverso ultima posizione e sarà automaticamente aggiornato ..

+0

Puoi puntare a una documentazione che dice che la vista non si aggiorna all'aggiunta di child it it? Inoltre, perché ha funzionato quando ho bloccato e sbloccato lo schermo? – Ashwin

+0

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.0_r1/android/view/ViewGroup.java#ViewGroup.addView%28android.view.View % 2Cint% 2Candroid.view.ViewGroup.LayoutParams% 29 ----- Controlla qui fuori che la misura non viene chiamata dopo aver aggiunto la vista secondaria ... e quando si blocca/sblocca lo schermo viene ricreata l'intera vista e questo è pari true se apri/chiudi tastiera, fai qualche gesto, ecc. –

+0

Cosa intendi per "la vista è stata ricreata"? Vuoi dire ridisegnato? – Ashwin

1

Un anno fa, mentre stavo lavorando su una libreria per la creazione dinamica di layout da file XML, ero abituato a lottare contro problemi comuni (come Android non supporta questo). Così, quando si aggiunge dinamicamente una vista ad un RelativeLayout si deve prendere in considerazione un paio di cose:

  1. creare il contenitore View (in questo caso il RelativeLayout)
  2. Creare tutte le viste senza assegnare alcun parametro di layout.
  3. Aggiungere tutte le viste secondarie al contenitore.
  4. Iterate sui figli del contenitore e popolano i parametri di layout di ogni bambino. Ciò è necessario perché quando vengono applicati i vincoli relazionali viene generato un Excpetion se manca il relativo View (non è stato precedentemente aggiunto al contenitore).

Questo è un codice di esempio tratto dal progetto su cui ho lavorato. Tieni presente che è solo una parte, quindi contiene riferimenti a classi che non sono definite nell'API di Android. Sono sicuro che vi darà l'idea di base di creazione dinamica RelativeLayot:

private void setChildren(RelativeLayout layout, T widget, 
     InflaterContext inflaterContext, Context context, 
     Factory<Widget, View> factory) { 
    List<Widget> children = widget.getChildren(); 
    if (Utils.isEmpty(children))) { 
     return; 
    } 

    // 1. create all children 
    for (Widget child : children) { 
     View view = factory.create(inflaterContext, context, child); 
     layout.addView(view); 
    } 

    // 2. Set layout parameters. This is done all children are created 
    // because there are relations between children. 
    for (Widget child : children) { 
     try { 
      View view = ViewIdManager.getInstance().findViewByName(layout, child.getId()); 

      if (view != null) { 
       populateLayoutParmas(child, view); 
      } 
     } catch (IndexNotFoundException e) { 
      Log.e(LOG_TAG, "Cannot find a related view for " + child.getId(), e); 
     } 
    } 
} 
0


 
//Declare globally 
 
LinearLayout[] layout; 
 
\t ImageView[] imageView1; 
 
\t ImageView[] imageView2; 
 
\t ImageView[] imageView3; 
 

 
// Initialize your layout. It would be RelativeLayout too. Just reference to it. 
 
LinearLayout ll = (LinearLayout) findViewById(R.id.mylinear); 
 
\t \t 
 

 
     // set listview row size as your demand 
 
\t \t layout = new LinearLayout[200]; 
 
\t \t imageView1 = new ImageView[200]; 
 
\t \t imageView2 = new ImageView[200]; 
 
\t \t imageView3 = new ImageView[200]; 
 

 
\t \t for (int i = 0; i < 200; i++) { 
 
\t \t \t layout[i] = new LinearLayout(this); 
 
\t \t \t layout[i].setBackgroundResource(R.drawable.book_shelf); 
 
\t \t \t // layout[i].setLayoutParams(new 
 
\t \t \t // LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, 
 
\t \t \t // 120)); 
 
\t \t \t layout[i].setLayoutParams(new LinearLayout.LayoutParams(
 
\t \t \t \t \t android.widget.LinearLayout.LayoutParams.FILL_PARENT, 220)); 
 

 
\t \t \t imageView1[i] = new ImageView(this); 
 
\t \t \t imageView2[i] = new ImageView(this); 
 
\t \t \t imageView3[i] = new ImageView(this); 
 

 
\t \t \t imageView1[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 
 
\t \t \t \t \t 0.33f)); 
 
\t \t \t imageView1[i].setPadding(0, 20, 0, 0); 
 

 
\t \t \t imageView1[i].setImageResource(R.drawable.bibid_one_bankim); 
 
\t \t \t imageView2[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 
 
\t \t \t \t \t 0.33f)); 
 
\t \t \t imageView2[i].setPadding(0, 20, 0, 0); 
 
\t \t \t imageView2[i].setImageResource(R.drawable.bibid_two_bankim); 
 

 
\t \t \t imageView3[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 
 
\t \t \t \t \t 0.33f)); 
 
\t \t \t imageView3[i].setImageResource(R.drawable.dena_pawna); 
 
\t \t \t imageView3[i].setPadding(0, 20, 0, 0); 
 

 
\t \t \t layout[i].setId(i); 
 
\t \t \t layout[i].setClickable(true); 
 
\t \t \t final int j = i; 
 

 
\t \t \t layout[i].addView(imageView1[i]); 
 
\t \t \t layout[i].addView(imageView2[i]); 
 
\t \t \t layout[i].addView(imageView3[i]); 
 

 
\t \t \t ll.addView(layout[i]); 
 
\t \t } 
 
\t }