0

У меня есть вид ресайклера, который состоит из нескольких таймеров обратного отсчета для каждой строки. Теперь мне удалось получить текстовое представление в соответствии с таймером обратного отсчета, но когда время закончится, я хочу изменить текстовое представление, чтобы отображать «Время закончилось» вместо подсчета.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

Попробуйте

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

Это не то, что я ищу. Также время будет по-прежнему отсчитываться после минут и секунд до 0. –

0

Ваш код является излишне чрезмерно сложным, но когда вы получаете обновления ваш TextView текст использовать простой тройной оператор, как это:

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

Предположим resultText Строка вар является результат, который вы получаете от вашего runnable.

+0

Но с тем, что вы предлагаете, таймер обратного отсчета все равно будет считать время. Я пытаюсь пропустить держатели, которые были закончены. –

+0

Ну, если условие выше верно, вы можете остановить свою работоспособность, также вы должны проверить класс «Дата» для удобства чтения человеком. –

+0

Как я могу точно остановить runnable, если нужно проверить больше держателей? Я не уверен в этом –