2015-06-19 19 views
7

Nella mia app, devo mostrare il conto alla rovescia per ogni oggetto in listview. Sono stato in grado di farlo usando CountDownTimer. Ma il problema è quando si scorre la vista elenco su o giù, il timer inizia a lampeggiare. Ho cercato molto ma non ho trovato una soluzione.ListView con timer a tempo reale. Timer sfarfallio durante lo scorrimento della listview

La mia classe adattatore

public class BuyListingListAdapter extends BaseAdapter { 

private Context mContext; 
private ArrayList<VehicleAttributes> mVehicleList = new ArrayList<VehicleAttributes>(); 
private Date currentDate; 
//Saving position in map to check if timer has been //started for this row 
private HashMap<Integer, Boolean> timerMap = new HashMap<Integer, Boolean>(); 

public BuyListingListAdapter(Context context, 
     ArrayList<VehicleAttributes> vehicleList, boolean showGridView) { 
    this.mContext = context; 
    this.mVehicleList = vehicleList; 
    this.showGridView = showGridView; 
    currentDate = new Date(System.currentTimeMillis()); 

    int listSize = mVehicleList.size(); 
    for (int i = 0; i < listSize; i++) 
     timerMap.put(i, false); 
} 

@Override 
public int getCount() { 
    return mVehicleList.size(); 
} 

@Override 
public Object getItem(int position) { 
    return mVehicleList.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return 0; 
} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    final ViewHolder holder; 
    if (convertView == null) { 
     LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 
     convertView = inflater.inflate(R.layout.row_buy_listing_grid, 
        parent, false); 
     holder = new ViewHolder(); 
        holder.timer_layout = (LinearLayout) convertView 
       .findViewById(R.id.timer_layout); 
        holder.txt_remaining_days = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_days); 
     holder.txt_remaining_hours = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_hours); 
     holder.txt_remaining_mins = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_mins); 
     holder.txt_remaining_secs = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_secs); 
     holder.listing_status = (ImageView) convertView 
       .findViewById(R.id.listing_status); 

     convertView.setTag(holder); 
    } else 
     holder = (ViewHolder) convertView.getTag(); 

    final VehicleAttributes vehicleAttributes = mVehicleList.get(position); 

    AuctionModel mAuctionModel = vehicleAttributes.getAuctionDetailModel(); 
    if (mAuctionModel != null) { 
     holder.img_auction.setVisibility(View.VISIBLE); 

     Date auctionStartDate = Util 
       .getDateFromString(mAuctionModel.getStarted_at(), 
         "yyyy-MM-dd hh:mm:ss", "GMT"); 
     Date auctionEndDate = Util.getDateFromString(
       mAuctionModel.getEnded_at(), "yyyy-MM-dd hh:mm:ss", "GMT"); 
     long diff = currentDate.getTime() - auctionEndDate.getTime(); 

     if (diff < 0) 
      diff = -diff; 
     else 
      diff = 0; 

     if (timerMap.get(position) == null || !timerMap.get(position)) { 

      timerMap.put(position, true); 
      MyCountDown countDown = new MyCountDown(position, diff, 1000, 
        holder.txt_remaining_days, holder.txt_remaining_hours, 
        holder.txt_remaining_mins, holder.txt_remaining_secs); 
      countDown.start(); 
     } 
    } 
    return convertView; 
} 

private class MyCountDown extends CountDownTimer { 
    RobotoCondensedBoldTextView txt_remaining_days; 
    RobotoCondensedBoldTextView txt_remaining_hours; 
    RobotoCondensedBoldTextView txt_remaining_mins; 
    RobotoCondensedBoldTextView txt_remaining_secs; 
    int position; 

    public MyCountDown(int position, long millisInFuture, long countDownInterval, 
      RobotoCondensedBoldTextView txt_remaining_days, 
      RobotoCondensedBoldTextView txt_remaining_hours, 
      RobotoCondensedBoldTextView txt_remaining_mins, 
      RobotoCondensedBoldTextView txt_remaining_secs) { 
     super(millisInFuture, countDownInterval); 
     this.position = position; 
     this.txt_remaining_days = txt_remaining_days; 
     this.txt_remaining_hours = txt_remaining_hours; 
     this.txt_remaining_mins = txt_remaining_mins; 
     this.txt_remaining_secs = txt_remaining_secs; 
    } 

    @Override 
    public void onFinish() { 

    } 

    @Override 
    public void onTick(long millisUntilFinished) { 
     updateTimerLabel(position, millisUntilFinished, txt_remaining_days, 
       txt_remaining_hours, txt_remaining_mins, txt_remaining_secs); 
    } 
} 

private void updateTimerLabel(int position, long millis, 
     RobotoCondensedBoldTextView txt_remaining_days, 
     RobotoCondensedBoldTextView txt_remaining_hours, 
     RobotoCondensedBoldTextView txt_remaining_mins, 
     RobotoCondensedBoldTextView txt_remaining_secs) { 
    String days = String.format("%02d", 
      TimeUnit.MILLISECONDS.toDays(millis)); 
    String hours = String.format(
      "%02d", 
      TimeUnit.MILLISECONDS.toHours(millis) 
        - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS 
          .toDays(millis))); 
    String mins = String.format(
      "%02d", 
      TimeUnit.MILLISECONDS.toMinutes(millis) 
        - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS 
          .toHours(millis))); 
    String secs = String.format(
      "%02d", 
      TimeUnit.MILLISECONDS.toSeconds(millis) 
        - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS 
          .toMinutes(millis))); 

    txt_remaining_days.setText(days); 
    txt_remaining_hours.setText(hours); 
    txt_remaining_mins.setText(mins); 
    txt_remaining_secs.setText(secs); 
} 

static class ViewHolder { 
    NetworkImageView mVehicleImage; 
    RobotoCondensedBoldTextView txt_remaining_days, txt_remaining_hours, 
      txt_remaining_mins, txt_remaining_secs; 
    LinearLayout timer_layout; 
} 
} 
+0

Un problema si perde la parte else di questo if (mAuctionModel! = Null) { – Amsheer

+0

@Amsheer Ho adattato il mio codice e mostrato solo ciò che è rilevante. Inoltre, il timer sarà visibile solo se questo modello è presente – Nitish

+0

lo hai testato su più dispositivi/versioni di Android? – bernlim

risposta

1

UPDATE

Ho aggiornato la mia risposta qui uno sguardo: (E 'usi CardView con recyclerview ma lo stesso principio può essere applicato anche per ListView) How to change text based on time and date?

Bisogna fare attenzione quando si crea il istanza countdowntimer e quando si annulla. Se non si annulla il timer, aggiornerà le visualizzazioni errate.

2

Si dovrebbe essere separazione del vostro ListView e Countdown Timer in due frammenti per evitare interferenze non intenzionale. Android non è progettato per tale implementazione.

Frammenti è la strada da percorrere: http://developer.android.com/guide/components/fragments.html

Edit: Per il vostro caso, è possibile eseguire un database separato di temporizzatori per ogni elemento della lista, poi basta elencare i tuoi articoli nel vostro ListView. Quando un utente ha bisogno di conoscere i tempi, fa clic sul tuo listino, che chiama il database per l'ora corrente. L'ora corrente viene quindi mostrata sul listino. Questo NON è live, quindi il tempo non cambierà. Fare così eviterà il problema di sfarfallio.

+0

Devo mostrare il timer in ogni voce listview. Non ho ottenuto come questo risolve questo problema ? – Nitish

+0

Ok, capisco.Ho elaborato sopra per la vostra preoccupazione specifica – bernlim

3

Ok consente di parlare del problema prima

if (convertView == null) { 
     LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 
     convertView = inflater.inflate(R.layout.row_buy_listing_grid, 
        parent, false); 
     holder = new ViewHolder(); 
        holder.timer_layout = (LinearLayout) convertView 
       .findViewById(R.id.timer_layout); 
        holder.txt_remaining_days = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_days); 
     holder.txt_remaining_hours = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_hours); 
     holder.txt_remaining_mins = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_mins); 
     holder.txt_remaining_secs = (RobotoCondensedBoldTextView) convertView 
       .findViewById(R.id.txt_remaining_secs); 
     holder.listing_status = (ImageView) convertView 
       .findViewById(R.id.listing_status); 

     convertView.setTag(holder); 
    } else 
     holder = (ViewHolder) convertView.getTag(); 

Il codice di cui sopra nella vista elenco riutilizzerà la voce per i componenti, per esempio quando si carica una lista solo 6 elementi sono elencati nella lista stessa, visualizzazione elenco crea questi elementi ma quando scorri verso l'alto e verso il basso invece di creare un nuovo elemento riutilizzerà la stessa vista per le posizioni successive, quindi quando passi la vista per contare il timer per aggiornare l'orario stesso le stesse si aggiornano con un timer per il conto alla rovescia diverso

Ora quale sarà la soluzione, devi capire quali visualizzazioni di articoli sono visibili sul ghiaione n e interrompere il conto alla rovescia per altre visualizzazioni. o c'è un modo molto semplice ma non raccomandato perché può causare problema di memoria

LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 
    convertView = inflater.inflate(R.layout.row_buy_listing_grid, 
       parent, false); 
    holder = new ViewHolder(); 
       holder.timer_layout = (LinearLayout) convertView 
      .findViewById(R.id.timer_layout); 
       holder.txt_remaining_days = (RobotoCondensedBoldTextView) convertView 
      .findViewById(R.id.txt_remaining_days); 
    holder.txt_remaining_hours = (RobotoCondensedBoldTextView) convertView 
      .findViewById(R.id.txt_remaining_hours); 
    holder.txt_remaining_mins = (RobotoCondensedBoldTextView) convertView 
      .findViewById(R.id.txt_remaining_mins); 
    holder.txt_remaining_secs = (RobotoCondensedBoldTextView) convertView 
      .findViewById(R.id.txt_remaining_secs); 
    holder.listing_status = (ImageView) convertView 
      .findViewById(R.id.listing_status); 

    convertView.setTag(holder); 

semplice rimuovi if(convertview==null) e consentire gonfiare una nuova visualizzazione per ogni riga.

+1

questo decima l'intero punto del modello 'ViewHolder' per riciclare le viste limitate rispetto all'area di visualizzazione del vostro schermo – trpride

+0

Sì, lo so e solo per questo ho scritto questa dichiarazione " Ora quale sarà la soluzione, devi capire quali visualizzazioni di elementi sono visibili sullo schermo e interrompere il conto alla rovescia per altre visualizzazioni oppure esiste un modo molto semplice ma non consigliato perché potrebbe causare problemi di memoria " –