0

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?

Répondre

0

Essayez

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 == 0 && minutes == 0) 
      this.timeLeft.setText("Time is Over"); 
     else if (seconds < 10 && minutes < 10) 
      this.timeLeft.setText("0" + minutes + ":0" + seconds); 
    } 
+0

Ce n'est pas ce que je cherche. De plus, l'heure compte toujours après les minutes et les secondes atteignent 0. –

0

Votre code est inutilement trop complexe, mais quand vous arrivez à la mise à jour de votre texte TextView utiliser un opérateur ternaire simple comme ceci:

youTextView.setText(resultText.equals("00:00") ? "Time is over" : resultText); 

On suppose resultText chaîne var est le résultat que vous obtenez de votre runnable.

+0

Mais avec ce que vous suggérez, le compte à rebours comptait toujours l'heure. J'essaie de sauter les détenteurs qui étaient terminés. –

+0

Eh bien, si la condition ci-dessus est vraie, vous pouvez arrêter votre runnable, aussi vous devriez vérifier la classe "Date" pour faciliter les temps de lecture humaine. –

+0

Comment est-ce que je peux arrêter exactement le runnable si plus de détenteurs de vue doivent être vérifiés? Je ne suis pas sûr à ce sujet –