ListView与Coundown计时器。 滚动列表视图时计时器闪烁

在我的应用程序中,我必须在列表视图中显示每个项目的倒计时器。 我已经能够使用CountDownTimer来做到这一点。 但是,问题是滚动列表视图向上或向下,定时器开始闪烁。 search了很多,但没有得到解决办法。

我的适配器类

 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计时器。 滚动列表视图时计时器闪烁"

UPDATE

我更新了我的答案在这里看看:(这是使用cardview与recyclerview但同样的原则也可以应用于列表视图) 如何更改基于时间和date的文本?

当您创build倒计时实例并取消它时,您必须小心。 如果你不取消计时器,它将更新错误的观点。

好的,我们先来谈谈这个问题

 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个项目出现在列表上,列表视图创build这些项目,但是当你上下滚动而不是创build新项目时,它将重用相同的观点为下一个位置,所以当你通过你的观点countDown定时器更新时间相同的观点正在更新不同的倒数计时器

现在解决scheme是什么,你必须弄清楚哪些项目视图在屏幕上可见,并停止其他视图的倒数计时器。 或者有一个非常简单的方法,但不build议,因为它可能会导致内存问题

  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)简单的删除if(convertview==null)并允许为每一行膨胀一个新的视图。

您应该将您的列表视图和倒数计时器分成两个片段,以避免无意的干扰。 Android不是为这样的实现而devise的。

碎片是要走的路: http : //developer.android.com/guide/components/fragments.html

编辑:为你的情况,你可以运行一个单独的数据库定时器为每个列表项目,然后只列出你的项目在你的列表视图。 当用户需要知道时间时,他们点击您的listitem,它会调用当前的数据库。 当前时间显示在列表项上。 这是不活的,所以时间不会改变。 这样做可以避免闪烁问题。