I have a Recyclerview , and I need to display a countdown on every row.
Here is a similar question coutndown timers in listview It has a good solution ,
After 6 hours I finally found how to use it. However, I couldn't find the same way with the Runnable.
I'm using this code and it works for me:
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date event_date = dateFormat.parse(laterStart.toString());
current_date = dateFormat.parse(laterCurrent.toString());
Date diff = event_date.getTime() - current_date.getTime();
} catch (Exception e) {
e.printStackTrace();
}
//Very important code for some problems
if (holder.timer != null) {
holder.timer.cancel();
}
holder.timer = new CountDownTimer(diff, 900) {
@Override
public void onTick(long millisUntilFinished) {
long day = TimeUnit.MILLISECONDS.toDays(millisUntilFinished);
millisUntilFinished -= TimeUnit.DAYS.toMillis(day);
long hour = TimeUnit.MILLISECONDS.toHours(millisUntilFinished);
millisUntilFinished -= TimeUnit.HOURS.toMillis(hour);
long minute = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished);
millisUntilFinished -= TimeUnit.MINUTES.toMillis(minute);
long second = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished);
holder.timeText.setText(day+":"+hour+":"+minute+":"+second);
}
@Override
public void onFinish() {
}
}.start();
}
And RecycleView ViewHolder class:
public class ViewHolder extends RecyclerView.ViewHolder {
***your codes***
//Just add CountDownTimer
CountDownTimer timer;
*** your codes ***
}
Add a CountDownTimer member in the ViewHolder. In getView() set and start the counter, and don't forget to cancel any existing one in the same instance of ViewHolder. In onTick() you need to update the value on the display, not start the counter.
The Simple Solution Would Be:
Handler handler=new Handler();
handler.postDelayed(new UpdateTimerThread(holder),0);
public Class UpdateTimerThread implements Runnable{
Holder holder;
public UpdateTimerThread(Holder holder){
this.holder=holder;
}
@Override
public void run() {
lgetCreatedTime = lgetCreatedTime + 1000;
long diffSeconds;
long diffMinutes;
long diffHours;
diffSeconds = lgetCreatedTime / 1000 % 60;
diffMinutes = lgetCreatedTime / (60 * 1000) % 60;
diffHours = lgetCreatedTime / (60 * 60 * 1000) % 24;
holder.GameTimer.setText(String.format("%02d:%02d:%02d", diffHours, diffMinutes, diffSeconds));
handler.postDelayed(this,1000);
}
}
Note: 1.holder is the object of ViewHolder class
2.Create a class UpdateTimerThread implements Runnable
3.Convert Date and Time to long and store into lgetCreatedTime
4.Run Handler for every 1 Sec to tick the Time
Here you can check and download the source code of Countdown timers in a RecyclerView
activity_main.xml
<RelativeLayout android:layout_width=”match_parent”
android:layout_height=”match_parent”
xmlns:android=”http://schemas.android.com/apk/res/android”>
<android.support.v7.widget.RecyclerView
android:id=”@+id/recycler_view”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:scrollbars=”vertical” />
</RelativeLayout>
adapter_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dp"
android:padding="10dp"
android:id="@+id/tv_timer"/>
</LinearLayout>
MainActivity.java
package com.androidsolutionworld.multipletimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.LinearLayout;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ArrayList al_data = new ArrayList<>();
private Adapter obj_adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
al_data.add("1234");
al_data.add("1257");
al_data.add("100");
al_data.add("1547");
al_data.add("200");
al_data.add("500");
al_data.add("2000");
al_data.add("1000");
obj_adapter = new Adapter(al_data);
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(obj_adapter);
}
}
Custom Adapter:
import android.os.CountDownTimer;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class Adapter extends RecyclerView.Adapter{
private ArrayList al_data;
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView tv_timer;
CountDownTimer timer;
public MyViewHolder (View view){
super(view);
tv_timer = (TextView)view.findViewById(R.id.tv_timer);
}
}
public Adapter(ArrayList al_data) {
this.al_data = al_data;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.tv_timer.setText(al_data.get(position));
if (holder.timer != null) {
holder.timer.cancel();
}
long timer = Long.parseLong(al_data.get(position));
timer = timer*1000;
holder.timer = new CountDownTimer(timer, 1000) {
public void onTick(long millisUntilFinished) {
holder.tv_timer.setText("" + millisUntilFinished/1000 + " Sec");
}
public void onFinish() {
holder.tv_timer.setText("00:00:00");
}
}.start();
}
@Override
public int getItemCount() {
return al_data.size();
}
}
You can create CountDownTimer reference in ViewHolder class and create its instance in onBindViewHolder method of Adapter.
It works perfectly.
Tested Myself.