How to handle multiple countdown timers in ListView?

后端 未结 4 1915
挽巷
挽巷 2020-11-27 06:02

I have a listview (with a custom list adapter), I need to display a countdown on every row.

For example, if my list contains 4 items, I will have 4 rows. At this po

相关标签:
4条回答
  • 2020-11-27 06:41

    Please have a look on this Countdown Timer in listview android example.

    Custom Adapter

    import android.os.CountDownTimer;
    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.TextView;
    
    import java.util.ArrayList;
    public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder>{
    
    private ArrayList<String> al_data;
    
    public class MyViewHolder extends RecyclerView.ViewHolder
    {
        public TextView tv_timer;
        CountDownTimer timer;
    
        public MyViewHolder (View view){
            super(view);
            tv_timer = (TextView)view.findViewById(R.id.tv_timer);
    
        }
    
    
    }
    
    public Adapter(ArrayList<String> al_data) {
        this.al_data = al_data;
    }
    
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout,parent,false);
    
    
        return new MyViewHolder(view);
    }
    
    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
    
        holder.tv_timer.setText(al_data.get(position));
    
        if (holder.timer != null) {
            holder.timer.cancel();
        }
         long timer = Long.parseLong(al_data.get(position));
    
        timer = timer*1000;
    
        holder.timer = new CountDownTimer(timer, 1000) {
            public void onTick(long millisUntilFinished) {
              holder.tv_timer.setText("" + millisUntilFinished/1000 + " Sec");
            }
    
            public void onFinish() {
                holder.tv_timer.setText("00:00:00");
            }
        }.start();
    
    
    }
    
    @Override
    public int getItemCount() {
        return al_data.size();
    }
    
    
    
    }
    

    Main Activity

    package com.androidsolutionworld.multipletimer;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.widget.LinearLayout;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private ArrayList<String> al_data = new ArrayList<>();
    private Adapter obj_adapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        al_data.add("1234");
        al_data.add("1257");
        al_data.add("100");
        al_data.add("1547");
        al_data.add("200");
        al_data.add("500");
        al_data.add("2000");
        al_data.add("1000");
    
        obj_adapter = new Adapter(al_data);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(obj_adapter);
    }
    }
    

    Thanks

    0 讨论(0)
  • 2020-11-27 06:47

    Adapter class:-


    public class CountdownAdapter extends RecyclerView.Adapter { ArrayList mList; Context mContext;

    public CountdownAdapter(ArrayList<Long> mList, Context mContext) {
        this.mList = mList;
        this.mContext = mContext;
    }
    
    public class ViewHolder extends RecyclerView.ViewHolder {
        CountDownTimer timerCount;
        TextView mCountDownTxt;
    
        public ViewHolder(View convertView) {
            super(convertView);
            mCountDownTxt = (TextView)convertView.findViewById(R.id.countdown_text);
        }
    }
    
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }
    
    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        if(holder.timerCount==null) {
            holder.timerCount = new CountDownTimer(mList.get(position), 1000) {
                @Override
                public void onTick(long millis) {
                    String hms = String.format("%02d:%02d",  TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
                    holder.mCountDownTxt.setText(hms);
                }
    
                @Override
                public void onFinish() {
    
                }
            };
        }
        holder.mCountDownTxt.setVisibility(View.VISIBLE);
        holder.timerCount.start();
    }
    
    @Override
    public int getItemCount() {
        return mList.size();
    }
    

    }

    0 讨论(0)
  • 2020-11-27 06:52

    It might be late but this is recyclerView version using php and json based on excellent answer of @Eldhose M Babu. Hope to be helpful :)

    Adapter.java

        public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
    
        private Context context;
        private final List<ViewHolder> lstHolders;
        public List<Model> lst;
    
        private Handler mHandler = new Handler();
        private Runnable updateRemainingTimeRunnable = new Runnable() {
            @Override
            public void run() {
                synchronized (lstHolders) {
                    long currentTime = System.currentTimeMillis();
                    for (ViewHolder holder : lstHolders) {
                        holder.updateTimeRemaining(currentTime);
                    }
                }
            }
        };
    
        public Adapter(List<Model> lst, Context context){
            super();
            this.lst = lst;
            this.context = context;
            lstHolders = new ArrayList<>();
            startUpdateTimer();
        }
    
        private void startUpdateTimer() {
            Timer tmr = new Timer();
            tmr.schedule(new TimerTask() {
                @Override
                public void run() {
                    mHandler.post(updateRemainingTimeRunnable);
                }
            }, 1000, 1000);
        }
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list, parent, false);
            ViewHolder viewHolder = new ViewHolder(v);
            return viewHolder;
        }
    
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            holder.setData(lst.get(position));
            synchronized (lstHolders) {
                lstHolders.add(holder);
            }
            holder.updateTimeRemaining(System.currentTimeMillis());
        }
    
        @Override
        public int getItemCount() {
            return lst.size();
        }
    
        class ViewHolder extends RecyclerView.ViewHolder{
            public TextView textViewName;
            public TextView tvTimeRemaining;
            Model mModel;
    
            public void setData(Model item) {
                mModel = item;
                textViewName.setText(item.name);
                updateTimeRemaining(System.currentTimeMillis());
            }
    
            public void updateTimeRemaining(long currentTime) {
                long timeDiff = mModel.expirationTime - currentTime;
                if (timeDiff > 0) {
                    int seconds = (int) (timeDiff / 1000) % 60;
                    int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
                    int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
    
                    tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec");
                } else {
                    tvTimeRemaining.setText("Expired!!");
                }
            }
    
            public ViewHolder(View itemView) {
                super(itemView);
                tvTimeRemaining = (TextView) itemView.findViewById(R.id.cd);
                textViewName = (TextView) itemView.findViewById(R.id.textViewName);
            }
        }
    }
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
    private List<Model> lst;
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private RecyclerView.Adapter adapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
    
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        lst = new ArrayList<>();
        getData();
    
    
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });
    }
    
    private void getData(){
        final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false);
    
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://192.168.200.102/api.php",
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        loading.dismiss();
                        parseData(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
    
                    }
                });
    
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(jsonArrayRequest);
    }
    
    private void parseData(JSONArray array){
        for(int i = 0; i<array.length(); i++) {
            Model model = new Model();
            JSONObject json = null;
            try {
                json = array.getJSONObject(i);
                model.setexpirationTime(json.getLong("expirationTime"));
                model.setName(json.getString("name"));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            lst.add(model);
        }
    
        adapter = new Adapter(lst, this);
        recyclerView.setAdapter(adapter);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
    
        if (id == R.id.action_settings) {
            return true;
        }
    
        return super.onOptionsItemSelected(item);
    }}
    

    Model.java

    public class Model {
    public String name;
    public long expirationTime;
    
    public long getexpirationTime() {
        return expirationTime;
    }
    
    public void setexpirationTime(long expire) {
        this.expirationTime = expire;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }}
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context="here.math.MainActivity">
    
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay" />
    
        </android.support.design.widget.AppBarLayout>
    
        <include layout="@layout/content_main" />
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@android:drawable/ic_dialog_email" />
    
    </android.support.design.widget.CoordinatorLayout>
    

    content_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="here.math.MainActivity"
        tools:showIn="@layout/activity_main">
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </android.support.v7.widget.RecyclerView>
    </RelativeLayout>
    

    list.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp">
    
            <LinearLayout
                android:padding="@dimen/activity_horizontal_margin"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
    
                <TableLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
    
                    <TableRow>
                        <TextView
                            android:text="Expire time"
                            android:paddingRight="10dp"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
    
                        <TextView
                            android:id="@+id/cd"
                            android:textStyle="bold"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
    
                    </TableRow>
    
                    <TableRow>
                        <TextView
                            android:text="Name"
                            android:paddingRight="10dp"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
    
                        <TextView
                            android:id="@+id/textViewName"
                            android:textStyle="bold"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
    
                    </TableRow>
    
                </TableLayout>
            </LinearLayout>
        </android.support.v7.widget.CardView>
    
    </RelativeLayout>
    

    and for url part you can do something kind of:

    <?php
    
    $arr = array(
    array(
            'name' => "Android",
            'expirationTime' => 1456860322 * 1000, // timestamp multiply for display in milliseconds
    ),
    array(
            'name' => "Android 2",
            'expirationTime' => 1456900522 * 1000,
    ),
    array(
            'name' => "Android 3",
            'expirationTime' =>  1459509819 * 1000,
    ),
    array(
            'name' => "Android 4",
            'expirationTime' => 1457021950 * 1000,
    ),
    );
    
    echo json_encode($arr);
    
    0 讨论(0)
  • 2020-11-27 06:54

    Instead of trying to show the remaining time for all, the idea is to update the remaining time for the items which are visible.

    Please follow the following sample code and let me know :

    MainActivity :

    public class MainActivity extends Activity {
    
    private ListView lvItems;
    private List<Product> lstProducts;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        lvItems = (ListView) findViewById(R.id.lvItems);
        lstProducts = new ArrayList<>();
        lstProducts.add(new Product("A", System.currentTimeMillis() + 10000));
        lstProducts.add(new Product("B", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("C", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("D", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("E", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("F", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("G", System.currentTimeMillis() + 30000));
        lstProducts.add(new Product("H", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("I", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("J", System.currentTimeMillis() + 40000));
        lstProducts.add(new Product("K", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("L", System.currentTimeMillis() + 50000));
        lstProducts.add(new Product("M", System.currentTimeMillis() + 60000));
        lstProducts.add(new Product("N", System.currentTimeMillis() + 20000));
        lstProducts.add(new Product("O", System.currentTimeMillis() + 10000));
    
        lvItems.setAdapter(new CountdownAdapter(MainActivity.this, lstProducts));
    }
    
    private class Product {
        String name;
        long expirationTime;
    
        public Product(String name, long expirationTime) {
            this.name = name;
            this.expirationTime = expirationTime;
        }
    }
    
    
    public class CountdownAdapter extends ArrayAdapter<Product> {
    
        private LayoutInflater lf;
        private List<ViewHolder> lstHolders;
        private Handler mHandler = new Handler();
        private Runnable updateRemainingTimeRunnable = new Runnable() {
            @Override
            public void run() {
                synchronized (lstHolders) {
                    long currentTime = System.currentTimeMillis();
                    for (ViewHolder holder : lstHolders) {
                        holder.updateTimeRemaining(currentTime);
                    }
                }
            }
        };
    
        public CountdownAdapter(Context context, List<Product> objects) {
            super(context, 0, objects);
            lf = LayoutInflater.from(context);
            lstHolders = new ArrayList<>();
            startUpdateTimer();
        }
    
        private void startUpdateTimer() {
            Timer tmr = new Timer();
            tmr.schedule(new TimerTask() {
                @Override
                public void run() {
                    mHandler.post(updateRemainingTimeRunnable);
                }
            }, 1000, 1000);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = lf.inflate(R.layout.list_item, parent, false);
                holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct);
                holder.tvTimeRemaining = (TextView) convertView.findViewById(R.id.tvTimeRemaining);
                convertView.setTag(holder);
                synchronized (lstHolders) {
                    lstHolders.add(holder);
                }
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.setData(getItem(position));
    
            return convertView;
        }
    }
    
    private class ViewHolder {
        TextView tvProduct;
        TextView tvTimeRemaining;
        Product mProduct;
    
        public void setData(Product item) {
            mProduct = item;
            tvProduct.setText(item.name);
            updateTimeRemaining(System.currentTimeMillis());
        }
    
        public void updateTimeRemaining(long currentTime) {
            long timeDiff = mProduct.expirationTime - currentTime;
            if (timeDiff > 0) {
                int seconds = (int) (timeDiff / 1000) % 60;
                int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
                int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
                tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec");
            } else {
                tvTimeRemaining.setText("Expired!!");
            }
        }
    }
    }
    

    activity_main.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ListView
        android:id="@+id/lvItems"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
    </RelativeLayout>
    

    list_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">
    
    <TextView
        android:id="@+id/tvProduct"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Product Name"
        android:textSize="16dp"
        android:textStyle="bold" />
    
    <TextView
        android:id="@+id/tvTimeRemaining"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Time Remaining : " />
    
    </LinearLayout>
    
    0 讨论(0)
提交回复
热议问题