ListView/GridView with timer in Android.

By | July 19, 2016

Here is a simple example implementing ListView with timer in each row.

Timer in ListView

Model Class for row

We have a simple model class for each row in the ListView.

Item.java


package com.coderzheaven.listviewtimer;

import java.util.Timer;

public class Item {

    public String title;
    public int timeInSeconds;
    public Timer timer;

    public Timer getTimer() {
        return timer;
    }

    public void setTimer(Timer timer) {
        this.timer = timer;
    }

    public int getTimeInSeconds() {
        return timeInSeconds;
    }

    public void setTimeInSeconds(int timeInSeconds) {
        this.timeInSeconds = timeInSeconds;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Item(String title, int timeInSeconds) {
        this.title = title;
        this.timeInSeconds = timeInSeconds;
    }
}

Layout for the Listview row

Now we have the cell.xml which is the layout for each row.

<?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:layout_margin="3dp"
    android:background="@color/colorPrimary_lit"
    android:orientation="vertical">


    <Button
        android:id="@+id/btnStartTimer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_margin="2dp"
        android:padding="10dp"
        android:text="START"
        android:textColor="@android:color/black"
        android:textStyle="bold" />


    <TextView
        android:id="@+id/tvTimer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_margin="2dp"
        android:gravity="center"
        android:layout_toRightOf="@+id/btnStartTimer"
        android:layout_toLeftOf="@+id/btnStopTimer"
        android:padding="10dp"
        android:text="14:50:70"
        android:textColor="@android:color/white"
        android:textSize="30sp"
        android:textStyle="bold" />


    <Button
        android:id="@+id/btnStopTimer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_margin="2dp"
        android:padding="10dp"
        android:text="STOP"
        android:textColor="@android:color/black"
        android:textStyle="bold" />


</RelativeLayout>

Layout for the Activity

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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"
    tools:context="com.coderzheaven.listviewtimer.MainActivity">


    <GridView
        android:id="@+id/grid_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="3dp"
        android:horizontalSpacing="3dp"
        android:verticalSpacing="3dp"></GridView>
</RelativeLayout>

GridAdapter

Here goes our adapter for the List/Grid.


package com.coderzheaven.listviewtimer;

import android.content.Context;
import android.graphics.Typeface;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class GridAdapter extends BaseAdapter implements View.OnClickListener {

    private final static String TAG = GridAdapter.class.getSimpleName();

    private Context mContext;

    List<Item> allTables;
    LayoutInflater inflater;

    private final int TIMER_INTERVAL = 1000;    // 1 Second

    private Handler handler = null;

    Typeface custom_font;

    public GridAdapter(Context c, List<Item> allTables) {
        mContext = c;
        this.allTables = allTables;
        inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        custom_font = Typeface.createFromAsset(mContext.getAssets(), "fonts/RobotoCondensed-Regular.ttf");
    }

    public int getCount() {
        return allTables.size();
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        if (convertView == null) {

            convertView = inflater.inflate(R.layout.cell, null);

            holder = new ViewHolder();

            holder.tvTimer = (TextView) convertView.findViewById(R.id.tvTimer);
            holder.btnStart = (Button) convertView.findViewById(R.id.btnStartTimer);
            holder.btnStop = (Button) convertView.findViewById(R.id.btnStopTimer);

            holder.tvTimer.setTypeface(custom_font);
            holder.btnStart.setTypeface(custom_font);
            holder.btnStop.setTypeface(custom_font);

            convertView.setTag(holder);

        } else {

            holder = (ViewHolder) convertView.getTag();

        }

        holder.btnStart.setOnClickListener(this);
        holder.btnStop.setOnClickListener(this);

        holder.btnStart.setTag(position);
        holder.btnStop.setTag(position);

        Item item = allTables.get(position);

        if (null != item) {

            if (null == item.getTimer()) {
                holder.tvTimer.setText(convertToTimerString(0));
                holder.btnStart.setVisibility(View.VISIBLE);
                holder.btnStop.setVisibility(View.GONE);
            } else {
                holder.tvTimer.setText(convertToTimerString(item.getTimeInSeconds()));
                holder.btnStop.setVisibility(View.VISIBLE);
                holder.btnStart.setVisibility(View.GONE);
            }

        }

        return convertView;
    }

    String convertToTimerString(int seconds) {
        String timeString = null;

        int rem = seconds % 60;  // 150%60 = 30
        int minutes = seconds / 60;
        int hour = minutes / 60;

        String tempRem = String.valueOf(rem);
        String tempMin = String.valueOf(minutes);
        String tempHr = String.valueOf(hour);

        if (rem < 10)
            tempRem = "0" + rem;

        if (minutes < 10)
            tempMin = "0" + minutes;

        if (hour < 10)
            tempHr = "0" + hour;


        timeString = tempHr + ":" + tempMin + ":" + tempRem;

        return timeString;
    }

    @Override
    public void onClick(View v) {

        Item item = allTables.get((int) v.getTag());

        int position = (int) v.getTag();

        if (v.getId() == R.id.btnStartTimer) {

            Timer timer = new Timer();
            TimerTask updateTime = new CustomTimerTask(mContext, item, position);
            timer.scheduleAtFixedRate(updateTime, 1000, TIMER_INTERVAL);

            item.setTimeInSeconds(0);
            item.setTimer(timer);

            allTables.remove(position);
            allTables.add(position, item);

            notifyDataSetChanged();


        } else if (v.getId() == R.id.btnStopTimer) {

            Timer timer = item.getTimer();
            if (null != timer) {
                timer.cancel();
                timer = null;
            }

            item.setTimer(timer);

            allTables.remove(position);
            allTables.add(position, item);
            notifyDataSetChanged();


        }


    }

    private static class ViewHolder {

        TextView tvTimer;
        Button btnStart, btnStop;

    }


    // Our Custom Timer Class...

    class CustomTimerTask extends TimerTask {

        private Context context;
        private Handler mHandler = new Handler();
        Item item;
        int position;

        public CustomTimerTask(Context context, Item snookerTable, int position) {
            this.context = context;
            this.position = position;
            this.item = snookerTable;
        }

        @Override
        public void run() {

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    int curTime = item.timeInSeconds;
                    item.setTimeInSeconds(curTime + 1);
                    allTables.remove(position);
                    allTables.add(position, item);
                    notifyDataSetChanged();
                }
            });

        }

    }


}

MainActivity


package com.coderzheaven.listviewtimer;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.GridView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static int NUM_ROWS = 20;

    private GridAdapter gridAdapter;

    private List<Item> allTables = new ArrayList<Item>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView gridview = (GridView) findViewById(R.id.grid_view);
        gridAdapter = new GridAdapter(this, allTables);
        gridview.setAdapter(gridAdapter);

        for (int i = 0; i < NUM_ROWS; i++) {
            Item item = new Item("Row " + i, 0);
            allTables.add(item);
        }
    }
}

You can download the complete source code from here.

Leave a Reply

Your email address will not be published. Required fields are marked *