У меня есть вид ресайклера, который состоит из нескольких таймеров обратного отсчета для каждой строки. Теперь мне удалось получить текстовое представление в соответствии с таймером обратного отсчета, но когда время закончится, я хочу изменить текстовое представление, чтобы отображать «Время закончилось» вместо подсчета.CountDown timer set text view - android
У меня есть пользовательский объект держателя вида, который содержит ссылку на объект модели. Теперь у меня есть runnable
объект, который отвечает за подсчет времени, и у меня есть обработчик, который запускает runnable каждые 500 милли.
Теперь таймеры обратного отсчета работают очень хорошо, но когда время заканчивается, оно просто показывает мне «00:00» вместо того, чтобы отображать «Время истекает».
Вот мой код адаптера массива. Внутри него находится код для обработки таймеров обратного отсчета:
package bikurim.silverfix.com.bikurim.adapters;
import android.os.Handler;
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.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import bikurim.silverfix.com.bikurim.models.Family;
import bikurim.silverfix.com.bikurim.R;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.FamilyViewHolder> implements Filterable{
private ArrayList<Family> families;
private ArrayList<Family> dataSet;
private ArrayList<FamilyViewHolder> holders;
private static long currentMillis, timeLeft;
private Timer tmr;
private Handler handler = new Handler();
private Runnable updateRemainingTimeRunnable = new Runnable() {
@Override
public void run() {
synchronized (holders) {
for (FamilyViewHolder holder : holders) {
if(!holder.family.isTimeLeft) {
currentMillis = System.currentTimeMillis();
timeLeft = holder.family.time - currentMillis;
holder.family.time = currentMillis + timeLeft;
if(holder.family.time > currentMillis) {
holder.updateFormatTime(currentMillis);
} else {
holder.family.isTimeLeft = true;
holder.timeLeft.setText("הזמן נגמר");
notifyDataSetChanged();
}
}
}
}
}
};
private FamilyFilter filter;
private boolean flagSearch;
public RecyclerViewAdapter(ArrayList<Family> families) {
this.dataSet = families;
this.families = families;
holders = new ArrayList<FamilyViewHolder>();
startUpdateTimer();
}
private void startUpdateTimer() {
tmr = new Timer();
tmr.schedule(new TimerTask() {
@Override
public void run() {
handler.post(updateRemainingTimeRunnable);
}
}, 500, 500);
}
@Override
public FamilyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.family_list_item, parent, false);
FamilyViewHolder pvh = new FamilyViewHolder(v);
synchronized (holders) {
holders.add(pvh);
}
return pvh;
}
@Override
public void onBindViewHolder(FamilyViewHolder holder, int position) {
Family family = families.get(position);
holder.setData(family);
}
@Override
public int getItemCount() {
return families.size();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public Filter getFilter() {
if (filter == null)
filter = new FamilyFilter();
return filter;
}
public static class FamilyViewHolder extends RecyclerView.ViewHolder {
public TextView personLname;
public TextView timeLeft;
public TextView visitors;
public Family family;
public FamilyViewHolder(View itemView) {
super(itemView);
personLname = (TextView) itemView.findViewById(R.id.person_Lname);
visitors = (TextView) itemView.findViewById(R.id.visitors);
timeLeft = (TextView) itemView.findViewById(R.id.person_timeLeft);
}
public void setData(Family item) {
family = item;
personLname.setText(family.lastName);
visitors.setText("מבקרים: "+ family.visitorsNum);
updateFormatTime(System.currentTimeMillis());
}
public void updateFormatTime(long currentMillis) {
long timeLeft = family.time - currentMillis;
int seconds = (int) (timeLeft/1000) % 60;
int minutes = (int) ((timeLeft/(1000 * 60)) % 60);
if(seconds > 10 && minutes > 10)
this.timeLeft.setText(minutes + ":" + seconds);
else if(seconds > 10 && minutes < 10)
this.timeLeft.setText("0" + minutes + ":" + seconds);
else if (seconds < 10 && minutes > 10)
this.timeLeft.setText(minutes + ":0" + seconds);
else if (seconds < 10 && minutes < 10)
this.timeLeft.setText("0" + minutes + ":0" + seconds);
}
}
private class FamilyFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint.length() == 0 || constraint == null) {
results.values = dataSet;
results.count = dataSet.size();
Log.d("Constraint is empty", "TRUE");
} else {
ArrayList<Family> queryResults = new ArrayList<Family>();
for (Family f : dataSet) {
if (constraint.charAt(0) == f.lastName.toUpperCase().indexOf(0)){
queryResults.add(f);
}
else if (f.lastName.toUpperCase().contains(constraint.toString().toUpperCase())) {
queryResults.add(f);
}
}
results.values = queryResults;
results.count = queryResults.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// Now we have to inform the adapter about the new list filtered
families = (ArrayList<Family>) results.values;
notifyDataSetChanged();
}
}
public void stopThread() {
tmr.cancel();
}
}
Почему код не работает?
UPDATE: ИТАК мне удалось решить эту проблему, а просто поставить объект CountDownTimer в каждом ViewHolder, которые будут работать независимо друг от друга.
Сейчас, когда время истекло, на фоне представления элемента строки и таймер прекрасно меняется
Проблемы заключается в том, что, когда время первого элемента закончено, остальные строки страдают от этого (их фона изменен, но таймер по-прежнему учитывается).
Вот мой адаптер Теперь код:
package bikurim.silverfix.com.bikurim.adapters;
import android.content.Context;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import bikurim.silverfix.com.bikurim.Constants;
import bikurim.silverfix.com.bikurim.models.Family;
import bikurim.silverfix.com.bikurim.R;
import bikurim.silverfix.com.bikurim.utils.HolderListener;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.FamilyViewHolder> implements Filterable, HolderListener {
// last position holds the last position of the element that was added, for animation purposes
private int lastPosition = 0;
private Context context;
private ArrayList<Family> families;
private ArrayList<Family> dataSet;
private FamilyFilter filter;
private boolean flagSearch;
public RecyclerViewAdapter(Context context, ArrayList<Family> families) {
this.context = context;
this.dataSet = families;
this.families = families;
}
@Override
public FamilyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.family_list_item, parent, false);
FamilyViewHolder pvh = new FamilyViewHolder(v, this);
return pvh;
}
@Override
public void onBindViewHolder(FamilyViewHolder holder, int position) {
Family family = families.get(position);
holder.setData(family);
}
@Override
public int getItemCount() {
return families != null ? families.size() : 0;
}
/* The following 2 methods are an implementations of the HolderListener.
* Inside every view holder lies an instance of HolderListener, for communication between the two*/
@Override
public void startAnimationOnItem(FamilyViewHolder holder) {
setAnimation(holder.cardView, holder.getAdapterPosition());
}
@Override
public void onTimeEnds(Family family) {
Toast.makeText(context, family.lastName, Toast.LENGTH_SHORT).show();
}
public void removeData(int pos) {
families.remove(pos);
notifyItemRemoved(pos);
notifyItemRangeChanged(pos, getItemCount());
}
public static class FamilyViewHolder extends RecyclerView.ViewHolder {
public CardView cardView;
public TextView personLname;
public TextView timeLeft;
public TextView visitors;
public Family family;
private CountDownTimer timer;
private HolderListener listener;
public FamilyViewHolder(View itemView, HolderListener listener) {
super(itemView);
this.listener = listener;
cardView = (CardView) itemView.findViewById(R.id.cv);
personLname = (TextView) itemView.findViewById(R.id.person_Lname);
visitors = (TextView) itemView.findViewById(R.id.visitors);
timeLeft = (TextView) itemView.findViewById(R.id.person_timeLeft);
}
public void setData(Family item) {
family = item;
personLname.setText(family.lastName);
visitors.setText("מבקרים: " + family.visitorsNum);
setUpTimer();
}
public void setUpTimer() {
long timeLeftInMillis = family.time - System.currentTimeMillis();
timer = new CountDownTimer(timeLeftInMillis, 1000) {
public void onTick(long millisUntilFinished) {
timeLeft.setText(updateFormatTime(millisUntilFinished));
family.time = System.currentTimeMillis() + millisUntilFinished;
}
public void onFinish() {
notifyTimeEnd();
cancel();
}
};
timer.start();
}
public void notifyTimeEnd() {
family.isTimeLeft = true;
timeLeft.setText("הזמן נגמר ");
cardView.setBackgroundResource(R.color.time_up_bg);
listener.startAnimationOnItem(this);
listener.onTimeEnds(family);
}
}
/* Starts a slide in animation for a given Card View */
private void setAnimation(View viewToAnimate, int position) {
if(position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public static String updateFormatTime(long millisUntilFinished) {
String result = "";
int seconds = (int) (millisUntilFinished/1000) % 60;
int minutes = (int) ((millisUntilFinished/(1000 * 60)) % 60);
if (seconds > 10 && minutes > 10)
result = minutes + ":" + seconds;
else if (seconds > 10 && minutes < 10)
result = "0" + minutes +ing ":" + seconds;
else if (seconds < 10 && minutes > 10)
result = minutes + ":0" + seconds;
else if (seconds < 10 && minutes < 10)
result = "0" + minutes + ":0" + seconds;
return result;
}
}
В моей деятельности, у меня есть объект ItemTouchHelper для поддержки механизма салфетки для-удаления. Вот код для этого:
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
final int pos = viewHolder.getAdapterPosition();
AlertDialog.Builder builder = new AlertDialog.Builder(FamilyListActivity.this);
builder.setMessage(R.string.confirmation_message)
.setPositiveButton(R.string.proceed_confirmation_dialog, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
adapter.removeData(pos);
String name = ((RecyclerViewAdapter.FamilyViewHolder) viewHolder).family.lastName;
Toast.makeText(FamilyListActivity.this, "משפחת "+name+" נמחקה מהרשימה", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).setNegativeButton(R.string.cancel_confirmation_dialog, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
adapter.notifyItemChanged(pos);
dialog.dismiss();
}
});
builder.show();
}
};
Почему, когда один элемент удаляется, он влияет на все остальные элементы в списке?
Это не то, что я ищу. Также время будет по-прежнему отсчитываться после минут и секунд до 0. –