Here is a simple example implementing ListView with timer in each row.
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.