CountDown计时器设置文本视图 - android

时间:2016-07-02 17:00:37

标签: android android-recyclerview handler runnable countdowntimer

我有一个回收站视图,每行包含多个倒计时器。 现在,我已经设法根据倒计时器更新文本视图,但是当时间结束时,我想更改文本视图以显示"时间结束"而不是计数。

我有一个自定义视图持有者对象,它包含对Model对象的引用。 现在,我有一个可运行的

负责计算时间的对象,我有一个每500毫秒运行一次runnable的处理程序。

现在,倒数计时器工作得很好但是当时间结束时,它只是显示我" 00:00"而不是显示一个meesage"时间结束了"。

这是我的数组适配器代码。其中包含处理倒计时器的代码:

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();
    }
}

为什么代码不起作用?

更新: 好的,所以我设法解决了这个问题,但只是在每个将独立工作的ViewHolder中放置一个CountDownTimer对象。

现在时间到了,行项目视图和计时器的背景正在发生变化

问题是,当第一个项目的时间结束时,其他行会受此影响(它们的背景会改变,但计时器仍会正确计算)。

现在是我的适配器代码:

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();
            }
        };

为什么当一个项目删除时,它会影响列表中的所有其他项目?

2 个答案:

答案 0 :(得分: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);
    }

答案 1 :(得分:0)

您的代码不必要地过于复杂,但是当您进行更新时,TextView文本会使用这样一个简单的三元运算符:

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

假设resultText String var是您从runnable获得的结果。