2015-06-19 40 views
7

W mojej aplikacji muszę wyświetlać odliczanie dla każdego elementu w widoku listy. Udało mi się to zrobić za pomocą CountDownTimer. Ale problem polega na tym, że podczas przewijania listy w górę lub w dół, timer zaczyna migać. Szukaliśmy dużo, ale nie mogłem znaleźć rozwiązania.ListView z ustawionym czasem. Czasomierz miga podczas przewijania listy w widoku

Moja klasa Adapter

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

Jednego numeru brakuje Ci jeszcze tej części, jeśli (mAuctionModel! = Null) { – Amsheer

+0

@Amsheer Zindeksowałem mój kod i pokazałem tylko to, co jest istotne. Ponadto, zegar będzie widoczny tylko wtedy, gdy ten model jest obecny – Nitish

+0

czy przetestowałeś to na wielu urządzeniach/wersjach Androida? – bernlim

Odpowiedz

1

UPDATE

zaktualizowałem moją odpowiedź tutaj przyjrzeć: (To zastosowania cardview z recyclerview ale ta sama zasada może być stosowana również do ListView) How to change text based on time and date?

Trzeba dbać podczas tworzenia instancja countdowntimer i kiedy ją anulujesz. Jeśli nie anulujesz licznika, zaktualizuje on nieprawidłowe widoki.

2

Powinieneś oddzielając swoje listview i odliczanie czasomierze na dwa fragmenty, aby uniknąć niezamierzonych zakłóceń. Android nie jest przeznaczony do takiej implementacji.

Fragmenty jest do zrobienia: http://developer.android.com/guide/components/fragments.html

Edit: Twoim przypadku można uruchomić oddzielną bazę liczniki dla każdego elementu listy, a potem po prostu wymienić swoje przedmioty w ListView. Gdy użytkownik potrzebuje znać czas, klika na liście, która wywołuje bazę danych w bieżącym czasie. Ten aktualny czas jest następnie wyświetlany na liście. To NIE jest aktywne, więc czas się nie zmieni. Pozwoli to uniknąć problemu z migotaniem.

+0

Muszę pokazać timer w każdej pozycji listview. Nie rozumiem jak to rozwiązuje ten problem ? – Nitish

+0

Ok Widzę.Powyżej podałem konkretną kwestię: – bernlim

3

Ok porozmawiajmy o pierwszej problemu

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(); 

Powyższy kod w widoku listy będzie ponownego wykorzystania elementu komponentów, na przykład, kiedy załadować listę tylko 6 pozycje są wyświetlane na liście widoku listy utwórz te elementy, ale gdy przewiniesz w górę lub w dół zamiast tworzyć nowy element, będzie on ponownie używał tego samego widoku dla następnych pozycji, więc gdy przejdziesz do widoku licznika CountDown, aby zaktualizować czas aktualizowania tych samych widoków za pomocą różnych minutników

Teraz, co będzie rozwiązaniem, musisz dowiedzieć się, które widoki przedmiotów są widoczne na piargu n i zatrzymać minutnik dla innych widoków. lub istnieje bardzo prosty sposób, ale nie zalecane, ponieważ może to spowodować problem pamięci

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); 

Proste usuń if(convertview==null) i pozwalają pompowania nowy widok dla każdego wiersza.

+1

to zdziesiątkuje cały punkt wzoru 'ViewHolder', aby odtworzyć ograniczone widoki w odniesieniu do obszaru wyświetlania twojego ekranu. – trpride

+0

Tak, wiem i tylko z tego powodu napisałem to oświadczenie " Teraz jakie będzie rozwiązanie, musisz dowiedzieć się, które widoki przedmiotów są widoczne na ekranie i zatrzymać minutnik dla innych widoków lub istnieje bardzo prosty sposób, ale nie jest to zalecane, ponieważ może to powodować problemy z pamięcią " –