我有一个Recyclerview
,我需要在每一行显示一个倒计时。
这是一个类似的问题 coutndown timers in listview 它有一个很好的解决方案,但我需要使用recyclerview
它有一个很好的解决方案,但我需要使用recyclerview
修改
我在尝试,这是我的代码适配器
MyAdapter
:
public class AdapterItems extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<TopCompetitions> mListItems = new ArrayList<>();
private ImageLoader mImageLoader;
private Context context;
private Handler handler;
/******************************************/
String current_date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = null;
Date d2 = null;
long diff;
long diffSeconds;
long diffMinutes;
long diffHours;
long diffDays;
String reachableDate = "";
/******************************************/
private ScheduledFuture updateFuture;
public AdapterItems(Context context) {
this.context = context;
mImageLoader = AppController.getInstance().getImageLoader();
}
public void setmListItems(ArrayList<TopCompetitions> mListItems) {
this.mListItems = mListItems;
//update the adapter to reflect the new set of mListItems
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.custom_horizontal_row, parent, false);
return new ItemHolder(itemView);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final TopCompetitions currentItem = mListItems.get(position);
final ItemHolder itemHolder = (ItemHolder) holder;
/* start_date , name_com_ar , name_com_en,
question_en,answer_ar1,answer_ar2,answer_ar3
,answer_en1,answer_en2,answer_en3,right_answer;
*/
itemHolder.item_id.setText(currentItem.getPrize_id());
itemHolder.item_description.setText(currentItem.getName_com_ar());
itemHolder.start_date.setText(currentItem.getStart_date());
itemHolder.end_date.setText(currentItem.getEnd_date());
itemHolder.name_com_ar.setText(currentItem.getName_com_ar());
itemHolder.name_com_en.setText(currentItem.getName_com_en());
itemHolder.answer_en1.setText(currentItem.getAnswer_en1());
itemHolder.answer_en2.setText(currentItem.getAnswer_en2());
itemHolder.answer_en3.setText(currentItem.getAnswer_en3());
itemHolder.answer_ar1.setText(currentItem.getAnswer_ar1());
itemHolder.answer_ar2.setText(currentItem.getAnswer_ar2());
itemHolder.answer_ar3.setText(currentItem.getAnswer_ar3());
itemHolder.right_answer.setText(currentItem.getRight_answer());
itemHolder.question_en.setText(currentItem.getQuestion_en());
itemHolder.question_ar.setText(currentItem.getQuestion_ar());
itemHolder.desc_ar.setText(currentItem.getPrize_desc_ar());
itemHolder.desc_en.setText(currentItem.getPrize_desc_en());
String urlLogo = currentItem.getPrize_pic1();
loadImages(urlLogo, itemHolder);
setDefferinceTimer(itemHolder , currentItem.getEnd_date());
if (updateFuture == null) {
final Handler mainHandler = new Handler(Looper.getMainLooper());
updateFuture = Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
setDefferinceTimer(itemHolder , currentItem.getEnd_date());
notifyDataSetChanged();
mainHandler.post(new Runnable() {
@Override
public void run() {
notifyDataSetChanged();
}
});
}
}, 0, 1000, TimeUnit.MILLISECONDS);
}
/* new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
startCountDown(itemHolder, currentItem.getEnd_date() + " 00:00:00");
notifyDataSetChanged();
}
public void onFinish() {
//counterTextView.setText("done!");
}
}.start();
}
});
*/
}
public void setDefferinceTimer(final RecyclerView.ViewHolder holder , String itemEndDate){
final ItemHolder itemHolder = (ItemHolder) holder;
current_date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
// reachableDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(itemEndDate);
try {
d1 = format.parse(current_date);
d2 = format.parse(itemEndDate+" 00:00:00");
} catch (ParseException e) {
e.printStackTrace();
}
diff = d2.getTime() - d1.getTime();
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000) % 24;
diffDays = diff / (24 * 60 * 60 * 1000);
itemHolder.days_tf.setText(""+diffDays);
itemHolder.hours_tf.setText(""+diffHours);
itemHolder.minutes_tf.setText(""+diffMinutes);
itemHolder.seconds_tf.setText(""+diffSeconds);
}
private void loadImages(String urlThumbnail, final RecyclerView.ViewHolder holder) {
final ItemHolder itemHolder = (ItemHolder) holder;
mImageLoader.get(urlThumbnail, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
itemHolder.item_image.setImageBitmap(response.getBitmap());
//holder.salon_gender.setImageBitmap(response.getBitmap());
}
@Override
public void onErrorResponse(VolleyError error) {
}
});
}
@Override
public int getItemCount() {
return mListItems.size();
}
private class ItemHolder extends RecyclerView.ViewHolder {
public TextView item_id, item_description, end_date,
start_date, name_com_ar, name_com_en, question_ar,
question_en, answer_ar1, answer_ar2, answer_ar3, answer_en1,
answer_en2, answer_en3, right_answer , desc_ar , desc_en;
public TextView days_tf, hours_tf, minutes_tf, seconds_tf;
public CircleImageView item_image;
public ItemHolder(View itemView) {
super(itemView);
start_date = (TextView) itemView.findViewById(R.id.start_date);
end_date = (TextView) itemView.findViewById(R.id.end_date);
name_com_ar = (TextView) itemView.findViewById(R.id.name_com_ar);
name_com_en = (TextView) itemView.findViewById(R.id.name_com_en);
question_en = (TextView) itemView.findViewById(R.id.question_en);
question_ar = (TextView) itemView.findViewById(R.id.question_ar);
desc_ar = (TextView) itemView.findViewById(R.id.desc_ar);
desc_en = (TextView) itemView.findViewById(R.id.desc_en);
answer_ar1 = (TextView) itemView.findViewById(R.id.answer_ar1);
answer_ar2 = (TextView) itemView.findViewById(R.id.answer_ar2);
answer_ar3 = (TextView) itemView.findViewById(R.id.answer_ar3);
answer_en1 = (TextView) itemView.findViewById(R.id.answer_en1);
answer_en2 = (TextView) itemView.findViewById(R.id.answer_en2);
answer_en3 = (TextView) itemView.findViewById(R.id.answer_en3);
right_answer = (TextView) itemView.findViewById(R.id.right_answer);
item_id = (TextView) itemView.findViewById(R.id.item_id);
item_description = (TextView) itemView.findViewById(R.id.item_description);
item_image = (CircleImageView) itemView.findViewById(R.id.item_image);
days_tf = (TextView) itemView.findViewById(R.id.days_tf);
hours_tf = (TextView) itemView.findViewById(R.id.hours_tf);
minutes_tf = (TextView) itemView.findViewById(R.id.minutes_tf);
seconds_tf = (TextView) itemView.findViewById(R.id.seconds_tf);
}
}
答案 0 :(得分:2)
在CountDownTimer
中添加ViewHolder
成员。在getView()
中设置并启动计数器,并且不要忘记在ViewHolder
的同一实例中取消任何现有的计数器。在onTick()
中,您需要更新显示屏上的值,而不是启动计数器。
答案 1 :(得分:2)
简单的解决方案是:
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);
}
}
注意: 1.holder是ViewHolder类的对象
2.创建一个类UpdateTimerThread实现Runnable
3.将日期和时间转换为长并存入lgetCreatedTime
4.Run Handler每1秒打勾时间
答案 2 :(得分:0)
您可以在ViewHolder类中创建CountDownTimer引用,并在适配器的onBindViewHolder方法中创建其实例。
效果很好。
自我测试。
答案 3 :(得分:0)
6小时后,我终于找到了使用方法。但是,我在Runnable中找不到相同的方式。
我正在使用此代码,它对我有用:
@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();
}
和RecycleView ViewHolder类:
public class ViewHolder extends RecyclerView.ViewHolder {
***your codes***
//Just add CountDownTimer
CountDownTimer timer;
*** your codes ***
}
答案 4 :(得分:0)
在这里我要扩展 AppCompatTextView
并在其中添加 CountDownTimer
。我正在处理 onStop
和 onStart
,以便 CountDownTimer
在后台不起作用。
class TimeCounterView : androidx.appcompat.widget.AppCompatTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
var countDownTimer: CountDownTimer? = null
fun startCountDown(expireTimeStamp: Long, removeItem: () -> Unit) {
stopCounter()
text = calculateTimeExpire(expireTimeStamp)//custom method to calculate time until expireTime
countDownTimer = object : CountDownTimer(
expireTimeStamp * 1000 - System.currentTimeMillis(),
ONE_MINUTE_MILLIS / 16
) {
override fun onTick(millisUntilFinished: Long) {
text = calculateTimeExpire(expireTimeStamp)
}
override fun onFinish() {
text = context.getString(R.string.choice_finished)
removeItem()
}
}
countDownTimer?.start()
}
fun stopCounter() {
countDownTimer?.cancel()
}
companion object {
const val ONE_MINUTE_MILLIS: Long = 60000
}
}
然后像这样在你的 itemview xml 中使用它作为普通视图
....
<com.example.custom.TimeCounterView
android:id="@+id/timeTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_weight="0"
android:textColor="@color/colorText"
tools:text="23:59" />
....
然后在您的适配器中,您将需要实现非常重要的方法 onViewRecycled
,该方法将被调用以从计时器对象中释放内存。
override fun onViewRecycled(holder: ChannelChoiceViewHolder) {
super.onViewRecycled(holder)
holder.stopCounter()
}
然后在持有人内你会这样做
fun bind(item: ChannelPageChoice, position: Int) {
//...
binding.timeTV.startCountDown(item.expire){ removeItem(position) }
//...
}
fun stopCounter() {
binding.timeTV.stopCounter()
}
然后在活动/片段中,您必须在 onStop 中将 recyclerview 设置为 null 并通过执行此操作在 onStart 中再次重新附加它 onViewRecycled
将在您的所有视图上调用,并且如果回收器将停止计时器在屏幕上不可见。
override fun onStop() {
super.onStop()
currentItemPosition =
(binding.recyclerView.layoutManager as? LinearLayoutManager)
?.findFirstVisibleItemPosition() ?: 0
binding.recyclerView.adapter = null
}
override fun onStart() {
super.onStart()
binding.recyclerView.adapter = myCustomAdapter
binding.recyclerView.scrollToPosition(currentItemPosition)
}
答案 5 :(得分:-1)
您可以在此处查看并下载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);
}
}
自定义适配器:
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();
}
}