Intereting Posts
Устройство BLE автоматически отключается от устройства Android. Android BLE Как отключить автоматический запуск приложения после сбоя (Android 2.2) Push-уведомление от UrbanAirship, не работающее с живым сервером (т. Е. С производственным ключом) в android Как получить количество предметов в прядильщике? Экран браузера браузера Android, screen.height & window.innerWidth & window.innerHeight ненадежны Режим ориентации «портрет» Как установить стиль ListView в ресурсе? Каков список задач, которые выполняет ConnectedAndroidTest? Android Calendar View для Date Picker Как направить уведомление клиенту, когда Firebase имеет новую запись? Есть ли способ сделать изображения на кнопках с автоматическим изменением размера в соответствии с экраном? Как использовать Unix-каналы в Android Заставить элемент ListView оставаться нажатым после нажатия? Что не так с жестко запрограммированной строкой в ​​файле android xml? Ошибка отладчика Android (MonoDroid)

ListView с таймером Coundown. Таймер мерцает при прокрутке списка

В моем приложении мне нужно показать таймер обратного отсчета для каждого элемента в списке. Я смог сделать это с помощью CountDownTimer . Но проблема заключается в прокрутке списка вверх или вниз, таймер начинает мерцать. Искал много, но не смог найти решение.

Класс моего адаптера

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

Solutions Collecting From Web of "ListView с таймером Coundown. Таймер мерцает при прокрутке списка"

ОБНОВИТЬ

Я обновил свой ответ здесь, посмотрите: (он использует cardview с recyclerview, но тот же принцип может применяться и для listview). Как изменить текст на основе времени и даты?

Вы должны заботиться о создании экземпляра countdowntimer и при его отмене. Если вы не отмените таймер, он обновит неверные представления.

Ok позволяет сначала поговорить о проблеме

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

Код выше в представлении списка будет повторно использовать элемент для компонентов, например, когда мы загружаем список, в списке отображаются только 6 элементов, просмотр списка создает эти элементы, но при прокрутке вверх и вниз вместо создания нового элемента он будет повторно использоваться Тот же вид для следующих позиций, поэтому, когда вы передаете свое представление countDown таймеру, чтобы обновить время, когда одни и те же представления обновляются с помощью другого таймера обратного отсчета

Теперь, каково будет решение, вам нужно выяснить, какие виды элементов видны на экране и остановить таймер обратного отсчета для других видов. Или есть очень простой способ, но не рекомендуется, поскольку это может вызвать проблемы с памятью

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

Просто удалите if(convertview==null) и разрешите раздувание нового представления для каждой строки.

Вы должны разделить таймеры просмотров и таймера на два фрагмента, чтобы избежать непреднамеренных помех. Android не предназначен для такой реализации.

Фрагменты – это путь: http://developer.android.com/guide/components/fragments.html

Изменить. В вашем случае вы можете запустить отдельную базу данных таймеров для каждого элемента списка, а затем просто перечислите свои элементы в своем списке. Когда пользователь должен знать время, они нажимают на ваш список, который вызывает базу данных в течение текущего времени. Это текущее время отображается в списке. Это НЕ живое, поэтому время не изменится. Это позволит избежать проблескивания.