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 *