2015-04-17 4 views
18

Sto utilizzando RecyclerView per visualizzare un elenco di segni e ogni segno del valore è mostrato come CardView. Ma alcuni contenuti delle carte vengono persi dopo lo scorrimento di RecyclerView in basso e lo scorrimento indietro, come mostrato nelle due schermate sottostanti. Il contenuto nel rettangolo rosso viene perso dopo lo scorrimento.Android: contenuto RecyclerView incasinato dopo lo scorrimento

PRIMA DELLA SCORRIMENTO; enter image description here

DOPO LO SCROLLING; enter image description here

mi chiedo anche se non si tratta di un bug di RecyclerView e trovare alcuna soluzione dopo Googling per esso.

Tutte le viste sono invisibili tranne il titolo, la loro visibilità dipende dal valore del marchio.

Qualcuno sa perché questo sarebbe successo?

+1

Ti suggerisco di scrivere componenti di visualizzazione personalizzati. La visibilità delle impostazioni non è una buona implementazione. Il tuo progetto è su Git? Quindi posso creare una richiesta di pull ad esso dostum;)? –

+0

Ti suggerisco caldamente * refactoring * il tuo codice prima di continuare. È estremamente difficile da seguire e hai VIE di molti punti di vista. Dovresti essere in grado di crearne molti in modo dinamico per ridurre il codice. Credo davvero che i problemi riguardino 'onBindViewHolder'. –

+0

@ EmreAktürk Sfortunatamente non è sul fatto che ha alcuni servizi web speciali dalla mia università. Cosa posso implementare con la visualizzazione personalizzata, non posso realizzare :) Non posso pensare che cosa fare, qualsiasi aiuto sarebbe grande. -JaredBurrows In realtà il servizio Web della visualizzazione è così sporco. Il servizio ha 10 campi Vize e tutti contengono i segni di lezione. Sto cercando di verificare se il campo Vize (mark) non è vuoto dal servizio, quindi mostra la vista testuale. –

risposta

22

onBindHolder chiamato più volte in quanto le news del riciclatore necessitano di una visualizzazione a meno che non siano nuove. Quindi, ogni volta che si imposta visilibity nelle viste secondarie, anche gli altri stati di visualizzazione cambiano.

Ogni volta che si scorre su e giù, queste visualizzazioni vengono ridisegnate con opzioni di visibilità errate.

Soluzione:

Hai un valori di controllo metodo setValue e impostato per visualizzare. Se necessario chiama un altro metodo "showView". È necessario implementare istruzione else (che è il valore è 0 o null) e hideView lì ...

void setValue(Object value, TextView textView, TableRow row, View seperator) { 
    if (value != null) { 
     if (!isEmpty(value.toString())) { 
      textView.setText(String.valueOf(value)); 
      showViews(row, seperator); 
     } 
    } else 
     hideViews(row, seperator); 
} 

private void showViews(TableRow row, View seperator) { 
    row.setVisibility(View.VISIBLE); 
    seperator.setVisibility(View.VISIBLE); 
} 

private void hideViews(TableRow row, View seperator) { 
    row.setVisibility(View.INVISIBLE); // if there is a empty space change it with View.GONE 
    seperator.setVisibility(View.INVISIBLE); 
} 
+0

Come sono pazzo, non l'ho pensato in quel modo. Mi hai salvato la vita, grazie mille. Kralsın :) –

+0

da dove verrà chiamato questo metodo ?? – kgandroid

+0

nel metodo OnBindHolder. –

0

Ciò è dovuto al riutilizzo delle viste durante lo scorrimento. Per risolvere questo problema è necessario ripristinare tutte le visualizzazioni che sono state rese visibili per altre celle (YUZME nell'esempio).

All'interno di setValue (valore dell'oggetto, TextView textView, riga TableRow, View seperator) rende semplicemente tutto txtVize * nascosto di nuovo.


vista Recycler inizia con 3 visualizzazioni:

[0] FIZ104

[1] MAT102

[2] REK361

Quando la vista viene fatto scorrere al le viste in basso [0] e [1] sono riciclate. Quando si torna alla vista superiore [2] si utilizza per visualizzare i dati contenuti in FIZ104 e MAT102 e tutte le modifiche apportate per REK361 sono ancora presenti.

+0

Grazie per la risposta. Conosco il meccanismo dei viewholder in realtà ciò che voglio fare è non riciclare le viste o mantenere i loro stati anche se l'utente scorre. Sto quasi cercando di capirlo circa 6 ore e ho provato tutto ma nessuno di loro ha funzionato. –

8

onBindHolder chiamato più volte come Recycler View ha bisogno di una vista a meno nuovo. Pertanto, ogni volta che si imposta visilibity nelle viste secondarie, anche gli altri stati di visualizzazione cambiano.

Ogni volta che si scorre su e giù, queste visualizzazioni vengono ridisegnate con opzioni di visibilità errate, quindi specificare sempre entrambe le condizioni perché la vista del riciclatore non conosce lo stato/le condizioni/i valori precedenti dei nostri widget.

Soluzione:

In caso di blocco Se si imposta la visibilità di qualsiasi widget.setVisibility Android (View.Gone) poi nel blocco else è necessario impostare E 'la visibilità di fronte vwith widget.setVisibility (View.Visible) da superare il problema precedente

@Override 
public void onBindViewHolder(ViewHolder viewHolder, int i) { 

    viewHolder.tvName.setText(ModelCategoryProducts.name.get(i)); 
    viewHolder.tvPrice.setText("Rs."+String.format("%.2f", Float.parseFloat(ModelCategoryProducts.price.get(i)))); 
    if(ModelCategoryProducts.special_price.get(i).equals("null")) { 
     viewHolder.tvSpecialPrice.setVisibility(View.GONE); // here visibility is gone and in else it's opposite visibility i set. 
     viewHolder.tvPrice.setTextColor(Color.parseColor("#ff0000")); 
     viewHolder.tvPrice.setPaintFlags(0);// here paint flag is 0 and in else it's opposite flag that i want is set. 
    }else if(!ModelCategoryProducts.special_price.get(i).equals("null")){ 
     viewHolder.tvPrice.setTextColor(Color.parseColor("#E0E0E0")); 
     viewHolder.tvSpecialPrice.setVisibility(View.VISIBLE); 
     viewHolder.tvSpecialPrice.setText("Rs." + String.format("%.2f", Float.parseFloat(ModelCategoryProducts.special_price.get(i)))); 
     viewHolder.tvPrice.setPaintFlags(viewHolder.tvPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); 
    } 
    if (!ModelCategoryProducts.image_url.get(i).isEmpty()) { 
     Picasso.with(context) 
       .load(ModelCategoryProducts.image_url.get(i)) 
       .into(viewHolder.ivProduct); 
    } 

    viewHolder.setClickListener(new ItemClickListener() { 
     @Override 
     public void onClick(View view, int position, boolean isLongClick) { 
      if (isLongClick) { 
//     Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position) + " (Long click)", Toast.LENGTH_SHORT).show(); 
      } else { 
       Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position), Toast.LENGTH_SHORT).show(); 
       Intent i = new Intent(context, ProductDetail.class); 
       i.putExtra("position",position); 
       i.putExtra("flagHlvCheck", 5); 
       context.startActivity(i); 
      } 
     } 
    }); 
} 
+1

Questo ragazzo ha ragione! –

19

Dopo aver combattuto con questo stesso problema per circa 24 ore, ho trovato una soluzione che ha funzionato per me. La chiave utilizzava il metodo setIsRecyclable() della classe RecyclerView.ViewHolder.

Questa è una sezione del mio codice onBindViewHolder().

@Override 
public void onBindViewHolder(final MyViewHolder holder, int position) { 
    final DataSource dataSource = dataSourceList.get(position); 

    holder.setIsRecyclable(false); 

    holder.name.setText(dataSource.getName()); 
    holder.active.setChecked(dataSource.getActive()); 

    String logoStr = dataSource.getLogo(); 

    //Logo 
    /** 
    * Do all the logo insertion stunts here 
    */ 
    /** 
    * Register the changes to the Switch 
    */ 
    holder.active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){ 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){ 
      dataSource.setActive(isChecked); 
     } 
    }); 
} 
+12

Questa non è affatto una soluzione, stai praticamente dicendo a recyclerView di non fare ciò che è stato fatto per fare, cioè riciclare le sue opinioni. La risposta accettata funziona bene. –

+0

Kinda sono d'accordo.Ma la risposta accettata non ha funzionato per me o potrebbe non essere in grado di seguire i passaggi poiché i collegamenti pubblicati da @Swisyn sono interrotti. Penso che Google deliberatamente creato 'RecyclerView.ViewHolder.setIsRecyclable()' per i casi in cui RecyclerView non dovrebbe riciclare viste o viste riciclaggio avere effetti negativi. – aphoe

+1

Sono d'accordo che forse non è la soluzione migliore, ma per me è l'unico che funziona dopo più di 24 ore cercando di trovare una soluzione. –

-1

Se si riscontrano problemi con il problema di visibilità per ex. se si è impostata la visibilità della vista in base alle condizioni, ma se si scorre verso il basso, le viste vengono aggiornate e la visibilità della vista all'interno dell'elemento di visualizzazione del riciclatore ottiene le modifiche e quindi viola la condizione.

Ecco una soluzione:

1. Innanzitutto, assegnare tag a quella vista di cui si desidera mantenere la visibilità.

holder.myImageView.setTag(myTeamLists.get(position)); 
    MyDTOClass checkWetherToShow=(MyDTOClass)holder.myImageView.getTag(); 

2. Ora applicare la sua condizione e attivare o disattivare la visibilità

if (checkWetherToShow.getHasToShowImage()){ 
     holder.myImageView.setVisibility(View.VISIBLE); 
    }else{ 
     holder.myImageView.setVisibility(View.GONE); 
    } 

La chiave per la risposta qui è Non dimenticare la parte else.