J'ai une vue recycleur qui consiste en plusieurs compteurs à rebours par rangée. Maintenant, j'ai réussi à mettre à jour l'affichage de texte en fonction du compte à rebours, mais quand le temps se termine, je veux changer la vue de texte pour afficher "Time is over" au lieu de compter.CountDown timer set text view - android
J'ai un objet support de vue personnalisé qui contient une référence à un objet Modèle. Maintenant, j'ai un runner
objet qui est responsable de compter l'heure, et j'ai un gestionnaire qui exécute le runnable tous les 500 millis.
Maintenant, les compteurs fonctionnent très bien mais quand le temps se termine, il me montre simplement "00:00" au lieu d'afficher un message "Time is over".
Voici mon code d'adaptateur de baie. A l'intérieur se trouve le code pour gérer le compte à rebours des minuteries:
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();
}
}
Pourquoi le code ne fonctionne pas?
MISE À JOUR: Ok, donc j'ai réussi à résoudre ce problème, mais il suffit de mettre un objet CountDownTimer dans tous les ViewHolder qui travailleront de façon indépendante.
Maintenant, lorsque le temps est écoulé, l'arrière-plan de la vue de l'élément de ligne et minuterie changent parfaitement
Le problème est que lorsque est terminé le temps du premier élément, les autres lignes sont affectées par ce (leur arrière-plan changé, mais la minuterie compte toujours correctement).
Voici mon code adaptateur maintenant:
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;
}
}
Dans mon activité, j'ai un objet ItemTouchHelper pour supporter un mécanisme swipe à supprimer. Voici le code pour cela:
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();
}
};
Pourquoi lorsqu'un élément est supprimé, cela affecte-t-il tous les autres éléments de la liste?
Ce n'est pas ce que je cherche. De plus, l'heure compte toujours après les minutes et les secondes atteignent 0. –