问题描述
我有一个列表视图(含自定义列表适配器),我需要显示在每一行倒计时。
I have a listview (with a custom list adapter), I need to display a countdown on every row.
例如,如果我的列表中包含4项,我将有4行。
在这一点上,我需要处理4个不同的倒计时(每个行),因为时间是不同的。
For example, if my list contains 4 items, I will have 4 rows.At this point, I need to handle 4 different countdowns (one for each row) because time is different.
到目前为止,我处理它的方式如下:在自定义列表适配器,里面getView()方法创建TextView的里面一个新的CountDownTimer并显示剩余时间。
So far, I'm handling it the following way : in the Custom List Adapter, inside getView() method I create a new CountDownTimer and display remaining time inside TextView.
但问题是,它减慢活动很多,我甚至不能正确地在最坏的情况下滚动(因为显示一排每一次,它会创建一个新的CountDownTimer)。
But the problem is that it slows the activity a lot, I can't even scroll correctly in the worst cases (because each time a row is displayed, it creates a new CountDownTimer).
我搜索了很多了更好的解决方案,但没有一个是令人满意的。
I searched a lot for a better solution, but no one was satisfying.
有一个更清洁,更平滑的解决方案来处理一个ListView内的多个倒计时?
Is there a cleaner and smoother solution to handle multiple countdown timers inside a listView ?
感谢
推荐答案
而不是试图显示所有的剩余时间,这个想法是,以更新其可见的物品的剩余时间。
Instead of trying to show the remaining time for all, the idea is to update the remaining time for the items which are visible.
请按照下面的示例code,让我知道:
Please follow the following sample code and let me know :
MainActivity:
MainActivity :
public class MainActivity extends Activity {
private ListView lvItems;
private List<Product> lstProducts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvItems = (ListView) findViewById(R.id.lvItems);
lstProducts = new ArrayList<>();
lstProducts.add(new Product("A", System.currentTimeMillis() + 10000));
lstProducts.add(new Product("B", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("C", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("D", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("E", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("F", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("G", System.currentTimeMillis() + 30000));
lstProducts.add(new Product("H", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("I", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("J", System.currentTimeMillis() + 40000));
lstProducts.add(new Product("K", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("L", System.currentTimeMillis() + 50000));
lstProducts.add(new Product("M", System.currentTimeMillis() + 60000));
lstProducts.add(new Product("N", System.currentTimeMillis() + 20000));
lstProducts.add(new Product("O", System.currentTimeMillis() + 10000));
lvItems.setAdapter(new CountdownAdapter(MainActivity.this, lstProducts));
}
private class Product {
String name;
long expirationTime;
public Product(String name, long expirationTime) {
this.name = name;
this.expirationTime = expirationTime;
}
}
public class CountdownAdapter extends ArrayAdapter<Product> {
private LayoutInflater lf;
private List<ViewHolder> lstHolders;
private Handler mHandler = new Handler();
private Runnable updateRemainingTimeRunnable = new Runnable() {
@Override
public void run() {
synchronized (lstHolders) {
long currentTime = System.currentTimeMillis();
for (ViewHolder holder : lstHolders) {
holder.updateTimeRemaining(currentTime);
}
}
}
};
public CountdownAdapter(Context context, List<Product> objects) {
super(context, 0, objects);
lf = LayoutInflater.from(context);
lstHolders = new ArrayList<>();
startUpdateTimer();
}
private void startUpdateTimer() {
Timer tmr = new Timer();
tmr.schedule(new TimerTask() {
@Override
public void run() {
mHandler.post(updateRemainingTimeRunnable);
}
}, 1000, 1000);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = lf.inflate(R.layout.list_item, parent, false);
holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct);
holder.tvTimeRemaining = (TextView) convertView.findViewById(R.id.tvTimeRemaining);
convertView.setTag(holder);
synchronized (lstHolders) {
lstHolders.add(holder);
}
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.setData(getItem(position));
return convertView;
}
}
private class ViewHolder {
TextView tvProduct;
TextView tvTimeRemaining;
Product mProduct;
public void setData(Product item) {
mProduct = item;
tvProduct.setText(item.name);
updateTimeRemaining(System.currentTimeMillis());
}
public void updateTimeRemaining(long currentTime) {
long timeDiff = mProduct.expirationTime - currentTime;
if (timeDiff > 0) {
int seconds = (int) (timeDiff / 1000) % 60;
int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec");
} else {
tvTimeRemaining.setText("Expired!!");
}
}
}
}
activity_main.xml中:
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lvItems"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
list_item.xml
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tvProduct"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Product Name"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvTimeRemaining"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Time Remaining : " />
</LinearLayout>
这篇关于如何处理ListView的多个倒计时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!