Android Multifunctional Clock Development Case (Practical)

  • 2021-07-18 09:01:20
  • OfStack

The first article introduces the basic content of Android multifunctional clock development, and you can review the development case of Android multifunctional clock (basic article)

Next, enter actual combat and learn quickly.

1. Clock

As we can see in the layout file, There is only one TextView on the interface, The function of this TextView is to display the current time of a system. At the same time, this time still jumps in 1 second and 1 second. To realize the jump of 1 second and 1 second, we need to refresh once every 1 second. At the same time, we also consider that when switching to another Tab, this time will not beat, which will reduce the occupation of the system. Considering this, we use Handler here, and judge whether to refresh the time through msg.what sent by handler.


public class TimeView extends LinearLayout { 
 
 private TextView tvTime; 
 public TimeView(Context context) { 
 super(context); 
 } 
 
 public TimeView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 } 
 
 public TimeView(Context context, AttributeSet attrs, int defStyle) { 
 super(context, attrs, defStyle); 
 } 
 
 @Override 
 protected void onFinishInflate() { 
 super.onFinishInflate(); 
 tvTime = (TextView) findViewById(R.id.tvTime); 
 //tvTime.setText("hello"); 
  
 timeHandler.sendEmptyMessage(0); 
 } 
 
 @Override 
 protected void onVisibilityChanged(View changedView, int visibility) { 
 super.onVisibilityChanged(changedView, visibility); 
 // When you switch to this again Tab We will send it again when 1 The next time this message is sent, if it is not, all messages will be removed  
 if (visibility == View.VISIBLE) { 
  timeHandler.sendEmptyMessage(0);  
 }else{ 
  timeHandler.removeMessages(0); 
 } 
 } 
 
 private void refreshTime(){ 
 // Get the current time  
 Calendar c = Calendar.getInstance(); 
  
 tvTime.setText(String.format("%d:%d:%d", c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE),c.get(Calendar.SECOND))); 
 } 
 private Handler timeHandler = new Handler(){ 
 public void handleMessage(android.os.Message msg) { 
  refreshTime(); 
  
  // In the current Tab Send a message to yourself when you can refresh  
  if (getVisibility() == View.VISIBLE) {  
  //1 Second to perform the following again sendEmptyMessage , what Parameter is used to distinguish between different message 
  timeHandler.sendEmptyMessageDelayed(0, 1000); 
  } 
 }; 
 }; 
} 

In fact, the Handler here can be completed with Timer and can achieve the same effect.

Here to mention 1 is onFinishInflate (), which we must use when we customize the layout. The explanations and examples are also available in the knowledge points uploaded later. Just look at that.

2. Alarm Clock

As we can see from the second layout, we used an ListView here, which is used to store the alarm clock we added. Since ListView is used here, we will then think of giving this ListView1 adapter adapter, so we will create such an adapter here.
private ArrayAdapter < AlarmData > adapter;

Seeing this, there may be questions again. What is AlarmData? Is there such a 1 data type? ? In fact, here we have customized a data type to store the alarm clock time created under 1. Let's look at 1 custom data type code!


//  Custom data type  
 private static class AlarmData { 
 private long time = 0; 
 private Calendar date; 
 private String timeLabel = ""; 
 
 public AlarmData(long time) { 
  this.time = time; 
  date = Calendar.getInstance(); 
  date.setTimeInMillis(time); 
  timeLabel = String.format("%d Month %d Day  %d:%d", 
   date.get(Calendar.MONTH) + 1, 
   date.get(Calendar.DAY_OF_MONTH), 
   date.get(Calendar.HOUR_OF_DAY), date.get(Calendar.MINUTE)); 
 } 
 
 public long getTime() { 
  return time; 
 } 
 
 public String getTimeLabel() { 
  return timeLabel; 
 } 
 
 public int getId() { 
  return (int) (getTime() / 1000 / 60); 
 } 
 
 @Override 
 public String toString() { 
  return getTimeLabel(); 
 } 
 
 } 

The code of this data type is actually very easy to understand, so I won't talk much about it.

When we get here, We haven't really finished it yet, If our code has been written, And it can be run. After we run it once, And added N alarm clocks. When we exit the program and open it again, we will find that the alarm clocks we created before are gone. The reason is that although we temporarily saved the data in ListView, we did not save it for a long time, so we will talk about saving these alarm clock data for a long time.


private void saveAlarmList() { 
 Editor editor = getContext().getSharedPreferences( 
  AlarmView.class.getName(), Context.MODE_PRIVATE).edit(); 
 
 StringBuffer sb = new StringBuffer(); 
 
 for (int i = 0; i < adapter.getCount(); i++) { 
  sb.append(adapter.getItem(i).getTime()).append(","); 
 } 
 if (sb.length() > 1) { 
  String content = sb.toString().substring(0, sb.length() - 1); 
  editor.putString(KEY_ALARM_LIST, content); 
 
  System.out.println(content); 
 } else { 
  editor.putString(KEY_ALARM_LIST, null); 
 } 
 editor.commit(); 
 } 

With saving, of course, we will think of reading


private void readSaveAlarmList() { 
 SharedPreferences sp = getContext().getSharedPreferences( 
  AlarmView.class.getName(), Context.MODE_PRIVATE); 
 String content = sp.getString(KEY_ALARM_LIST, null); 
 
 if (content != null) { 
  String[] timeStrings = content.split(","); 
  for (String string : timeStrings) { 
  adapter.add(new AlarmData(Long.parseLong(string))); 
  } 
 } 
 } 

The above 1 unfamiliar types can be viewed in the following knowledge points.

Then let's look at the most important thing is to add an alarm clock


private void addAlarm() { 
 
 Calendar c = Calendar.getInstance(); 
 
 new TPDiolog(getContext(), new TimePickerDialog.OnTimeSetListener() { 
 
  @Override 
  public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 
 
  Calendar calendar = Calendar.getInstance(); 
  calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
  calendar.set(Calendar.MINUTE, minute); 
  calendar.set(Calendar.SECOND, 0); 
  calendar.set(Calendar.MILLISECOND, 0); 
 
  Calendar currentTime = Calendar.getInstance(); 
  if (currentTime.getTimeInMillis() >= calendar.getTimeInMillis()) { 
   calendar.setTimeInMillis(calendar.getTimeInMillis() + 24 
    * 60 * 60 * 1000); 
  } 
  AlarmData ad = new AlarmData(calendar.getTimeInMillis()); 
  adapter.add(ad); 
  alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
   ad.getTime(), 5 * 60 * 1000, PendingIntent 
    .getBroadcast(getContext(), ad.getId(), 
     new Intent(getContext(), 
      AlarmReceiver.class), 0)); 
  saveAlarmList(); 
  } 
 }, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), true).show(); 
 } 

Here we can see TPDiolog, You may encounter the same problem when you try it yourself. That is, when you through the TimePickerDialog system time selection control, click OK, will create two records, this is because we click OK will call the event listener time, in the closing of the Dialog will also call 1, so we here rewrite 1 of the class method

TPDiolog.class


public class TPDiolog extends TimePickerDialog { 
 
 public TPDiolog(Context context, OnTimeSetListener callBack, int hourOfDay, 
  int minute, boolean is24HourView) { 
 super(context, callBack, hourOfDay, minute, is24HourView); 
 } 
 
 // Override this method to avoid calling it twice onTimeSet 
 @Override 
 protected void onStop() { 
 //super.onStop(); 
 } 
} 

In the previous code, we also saw an alarmManager object, which we created to invoke the alarm clock service of the system, so we created an AlarmReceiver. class


public class AlarmReceiver extends BroadcastReceiver { 
 
 @Override 
 public void onReceive(Context context, Intent arg1) { 
 System.out.println(" The alarm clock is on! "); 
  
 AlarmManager am=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
 am.cancel(PendingIntent.getBroadcast(context, getResultCode(), new Intent(context, AlarmReceiver.class), 0)); 
  
 Intent i =new Intent(context,PlayAlarmAty.class); 
 // Settings intent Startup mode of  
 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
 context.startActivity(i); 
 } 
 
} 

1 some small place to speak well, and finally put AlarmView. class complete code.


package com.example.clock; 
 
import java.util.Calendar; 
import java.util.Date; 
import java.util.Iterator; 
 
import android.app.AlarmManager; 
import android.app.AlertDialog; 
import android.app.PendingIntent; 
import android.app.TimePickerDialog; 
import android.app.TimePickerDialog.OnTimeSetListener; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.content.SharedPreferences.Editor; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemLongClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.ListView; 
import android.widget.Switch; 
import android.widget.TimePicker; 
 
public class AlarmView extends LinearLayout { 
 
 private Button btnAddAlarm; 
 private ListView lvListAlarm; 
 private ArrayAdapter<AlarmData> adapter; 
 private AlarmManager alarmManager; 
 
 public AlarmView(Context context, AttributeSet attrs, int defStyle) { 
 super(context, attrs, defStyle); 
 init(); 
 } 
 
 public AlarmView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 init(); 
 } 
 
 public AlarmView(Context context) { 
 super(context); 
 init(); 
 } 
 
 private void init() { 
 alarmManager = (AlarmManager) getContext().getSystemService( 
  Context.ALARM_SERVICE); 
 } 
 
 @Override 
 protected void onFinishInflate() { 
 super.onFinishInflate(); 
 btnAddAlarm = (Button) findViewById(R.id.btnAddAlarm); 
 lvListAlarm = (ListView) findViewById(R.id.lvListAlarm); 
 
 adapter = new ArrayAdapter<AlarmData>(getContext(), 
  android.R.layout.simple_list_item_1); 
 lvListAlarm.setAdapter(adapter); 
 
 readSaveAlarmList(); 
 // adapter.add(new AlarmData(System.currentTimeMillis())); 
 
 btnAddAlarm.setOnClickListener(new OnClickListener() { 
 
  @Override 
  public void onClick(View v) { 
  addAlarm(); 
  } 
 }); 
 //  Long press an item to delete  
 lvListAlarm.setOnItemLongClickListener(new OnItemLongClickListener() { 
 
  @Override 
  public boolean onItemLongClick(AdapterView<?> arg0, View arg1, 
   final int position, long arg3) { 
 
  new AlertDialog.Builder(getContext()) 
   .setTitle(" Operation options ") 
   .setItems(new CharSequence[] { " Delete ", " Delete 1" }, 
    new DialogInterface.OnClickListener() { 
 
     @Override 
     public void onClick(DialogInterface dialog, 
      int which) { 
     switch (which) { 
     case 0: 
      deleteAlarm(position); 
      break; 
 
     default: 
      break; 
     } 
     } 
    }).setNegativeButton(" Cancel ", null).show(); 
  return true; 
  } 
 }); 
 } 
 
 private void deleteAlarm(int position) { 
 AlarmData ad = adapter.getItem(position); 
 adapter.remove(ad); 
 saveAlarmList(); 
 
 alarmManager.cancel(PendingIntent.getBroadcast(getContext(), 
  ad.getId(), new Intent(getContext(), AlarmReceiver.class), 0)); 
 } 
 
 private void addAlarm() { 
 
 Calendar c = Calendar.getInstance(); 
 
 new TPDiolog(getContext(), new TimePickerDialog.OnTimeSetListener() { 
 
  @Override 
  public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 
 
  Calendar calendar = Calendar.getInstance(); 
  calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
  calendar.set(Calendar.MINUTE, minute); 
  calendar.set(Calendar.SECOND, 0); 
  calendar.set(Calendar.MILLISECOND, 0); 
 
  Calendar currentTime = Calendar.getInstance(); 
  if (currentTime.getTimeInMillis() >= calendar.getTimeInMillis()) { 
   calendar.setTimeInMillis(calendar.getTimeInMillis() + 24 
    * 60 * 60 * 1000); 
  } 
  AlarmData ad = new AlarmData(calendar.getTimeInMillis()); 
  adapter.add(ad); 
  alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
   ad.getTime(), 5 * 60 * 1000, PendingIntent 
    .getBroadcast(getContext(), ad.getId(), 
     new Intent(getContext(), 
      AlarmReceiver.class), 0)); 
  saveAlarmList(); 
  } 
 }, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), true).show(); 
 } 
 
 private static final String KEY_ALARM_LIST = "alarmlist"; 
 
 private void saveAlarmList() { 
 Editor editor = getContext().getSharedPreferences( 
  AlarmView.class.getName(), Context.MODE_PRIVATE).edit(); 
 
 StringBuffer sb = new StringBuffer(); 
 
 for (int i = 0; i < adapter.getCount(); i++) { 
  sb.append(adapter.getItem(i).getTime()).append(","); 
 } 
 if (sb.length() > 1) { 
  String content = sb.toString().substring(0, sb.length() - 1); 
  editor.putString(KEY_ALARM_LIST, content); 
 
  System.out.println(content); 
 } else { 
  editor.putString(KEY_ALARM_LIST, null); 
 } 
 editor.commit(); 
 } 
 
 private void readSaveAlarmList() { 
 SharedPreferences sp = getContext().getSharedPreferences( 
  AlarmView.class.getName(), Context.MODE_PRIVATE); 
 String content = sp.getString(KEY_ALARM_LIST, null); 
 
 if (content != null) { 
  String[] timeStrings = content.split(","); 
  for (String string : timeStrings) { 
  adapter.add(new AlarmData(Long.parseLong(string))); 
  } 
 } 
 } 
 
 //  Custom data type  
 private static class AlarmData { 
 private long time = 0; 
 private Calendar date; 
 private String timeLabel = ""; 
 
 public AlarmData(long time) { 
  this.time = time; 
  date = Calendar.getInstance(); 
  date.setTimeInMillis(time); 
  timeLabel = String.format("%d Month %d Day  %d:%d", 
   date.get(Calendar.MONTH) + 1, 
   date.get(Calendar.DAY_OF_MONTH), 
   date.get(Calendar.HOUR_OF_DAY), date.get(Calendar.MINUTE)); 
 } 
 
 public long getTime() { 
  return time; 
 } 
 
 public String getTimeLabel() { 
  return timeLabel; 
 } 
 
 public int getId() { 
  return (int) (getTime() / 1000 / 60); 
 } 
 
 @Override 
 public String toString() { 
  return getTimeLabel(); 
 } 
 
 } 
} 

3. Timer
The main function of the timer is that you set a time first. Then click Start, and the time will be reduced by 1 second and 1 second. Here, we mainly use the timer of Timer system. There is no difficult place in this code, and some places have been annotated, so paste the code directly. Some people may not know how to use Timer, which will be mentioned in later knowledge points.


package com.example.clock; 
 
import java.util.Timer; 
import java.util.TimerTask; 
 
import android.R.integer; 
import android.app.AlertDialog; 
import android.content.Context; 
import android.os.Handler; 
import android.text.Editable; 
import android.text.TextUtils; 
import android.text.TextWatcher; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.LinearLayout; 
 
public class TimerView extends LinearLayout { 
 
 public TimerView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 } 
 
 public TimerView(Context context) { 
 super(context); 
 } 
 
 @Override 
 protected void onFinishInflate() { 
 super.onFinishInflate(); 
 
 btnStart = (Button) findViewById(R.id.btnStart); 
 btnPause = (Button) findViewById(R.id.btnPause); 
 btnResume = (Button) findViewById(R.id.btnResume); 
 btnReset = (Button) findViewById(R.id.btnReset); 
 
 btnStart.setOnClickListener(new OnClickListener() { 
 
  @Override 
  public void onClick(View v) { 
  startTimer(); 
  btnStart.setVisibility(View.GONE); 
  btnPause.setVisibility(View.VISIBLE); 
  btnReset.setVisibility(View.VISIBLE); 
  } 
 }); 
  
 btnPause.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  stopTimer(); 
  btnPause.setVisibility(View.GONE); 
  btnResume.setVisibility(View.VISIBLE); 
  } 
 }); 
  
 btnResume.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  startTimer(); 
  btnPause.setVisibility(View.VISIBLE); 
  btnResume.setVisibility(View.GONE); 
  } 
 }); 
 btnReset.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  stopTimer(); 
  etHour.setText("00"); 
  etMin.setText("00"); 
  etSec.setText("00"); 
   
  btnReset.setVisibility(View.GONE); 
  btnResume.setVisibility(View.GONE); 
  btnPause.setVisibility(View.GONE); 
  btnStart.setVisibility(View.VISIBLE); 
  } 
 }); 
 
 etHour = (EditText) findViewById(R.id.etHour); 
 etMin = (EditText) findViewById(R.id.etMin); 
 etSec = (EditText) findViewById(R.id.etSec); 
 
 etHour.setText("00"); 
 etHour.addTextChangedListener(new TextWatcher() { 
 
  @Override 
  public void onTextChanged(CharSequence s, int start, int before, 
   int count) { 
  /* 
   *  This method is used in Text Object that triggers the call during the change process,   It means that in the original text s In,  
   *  From start Beginning count The replacement length of characters is before The old text of,  
   *  Note that there are no words like will, that is to say 1 Sentence performs a replacement action.  
   */ 
  if (!TextUtils.isEmpty(s)) { 
 
   int value = Integer.parseInt(s.toString()); 
 
   if (value > 59) { 
   etHour.setText("59"); 
   } else if (value < 0) { 
   etHour.setText("00"); 
   } 
  } 
  checkToEnableBtnStart(); 
  } 
 
  @Override 
  public void beforeTextChanged(CharSequence s, int start, int count, 
   int after) { 
  } 
 
  @Override 
  public void afterTextChanged(Editable s) { 
  } 
 }); 
 etMin.setText("00"); 
 etMin.addTextChangedListener(new TextWatcher() { 
 
  @Override 
  public void onTextChanged(CharSequence s, int start, int before, 
   int count) { 
  if (!TextUtils.isEmpty(s)) { 
 
   int value = Integer.parseInt(s.toString()); 
 
   if (value > 59) { 
   etMin.setText("59"); 
   } else if (value < 0) { 
   etMin.setText("00"); 
   } 
  } 
  checkToEnableBtnStart(); 
  } 
 
  @Override 
  public void beforeTextChanged(CharSequence s, int start, int count, 
   int after) { 
  } 
 
  @Override 
  public void afterTextChanged(Editable s) { 
  } 
 }); 
 etSec.setText("00"); 
 etSec.addTextChangedListener(new TextWatcher() { 
 
  @Override 
  public void onTextChanged(CharSequence s, int start, int before, 
   int count) { 
  if (!TextUtils.isEmpty(s)) { 
 
   int value = Integer.parseInt(s.toString()); 
 
   if (value > 59) { 
   etSec.setText("59"); 
   } else if (value < 0) { 
   etSec.setText("00"); 
   } 
  } 
  checkToEnableBtnStart(); 
  } 
 
  @Override 
  public void beforeTextChanged(CharSequence s, int start, int count, 
   int after) { 
  } 
 
  @Override 
  public void afterTextChanged(Editable s) { 
  } 
 }); 
 
 btnStart.setVisibility(View.VISIBLE); 
 btnStart.setEnabled(false); 
 btnPause.setVisibility(View.GONE); 
 btnResume.setVisibility(View.GONE); 
 btnReset.setVisibility(View.GONE); 
 } 
 
 private void checkToEnableBtnStart() { 
 btnStart.setEnabled((!TextUtils.isEmpty(etHour.getText()) && Integer 
  .parseInt(etHour.getText().toString()) > 0) 
  || (!TextUtils.isEmpty(etMin.getText()) && Integer 
   .parseInt(etMin.getText().toString()) > 0) 
  || (!TextUtils.isEmpty(etSec.getText()) && Integer 
   .parseInt(etSec.getText().toString()) > 0)); 
 } 
 
 private void startTimer() { 
 if (timerTask == null) { 
  allTimeCount = Integer.parseInt(etHour.getText().toString()) * 60 
   * 60 + Integer.parseInt(etMin.getText().toString()) * 60 
   + Integer.parseInt(etSec.getText().toString()); 
  timerTask = new TimerTask() { 
 
  @Override 
  public void run() { 
   allTimeCount--; 
   handle.sendEmptyMessage(MSG_WHAT_TIME_TICK); 
   if (allTimeCount <= 0) { 
   handle.sendEmptyMessage(MSG_WHAT_TIME_IS_UP); 
   stopTimer(); 
   } 
  } 
  }; 
  timer.schedule(timerTask, 1000, 1000); 
 } 
 } 
 private void stopTimer(){ 
 if (timerTask!=null) { 
  timerTask.cancel(); 
  timerTask=null; 
 } 
 } 
 
 private Handler handle = new Handler(){ 
  
 public void handleMessage(android.os.Message msg) { 
  switch (msg.what) { 
  case MSG_WHAT_TIME_TICK: 
  int hour = allTimeCount/60/60; 
  int min = (allTimeCount/60)%60; 
  int sec = allTimeCount%60; 
   
  etHour.setText(hour+""); 
  etMin.setText(min+""); 
  etSec.setText(sec+""); 
  break; 
   
  case MSG_WHAT_TIME_IS_UP: 
  new AlertDialog.Builder(getContext()) 
  .setTitle("Time is up!") 
  .setMessage("Time is up!") 
  .setNegativeButton("Cancle", null).show(); 
   
  btnReset.setVisibility(View.GONE); 
  btnResume.setVisibility(View.GONE); 
  btnPause.setVisibility(View.GONE); 
  btnStart.setVisibility(View.VISIBLE); 
  break; 
 
  default: 
  break; 
  } 
 }; 
 }; 
 private static final int MSG_WHAT_TIME_IS_UP = 1; 
 private static final int MSG_WHAT_TIME_TICK = 2; 
 
 private int allTimeCount = 0; 
 private Timer timer = new Timer(); 
 private TimerTask timerTask = null; 
 private Button btnStart, btnPause, btnResume, btnReset; 
 private EditText etHour, etMin, etSec; 
 
} 

4. Stopwatch
I believe everyone is familiar with the last stopwatch, and the knowledge used is just mentioned in the previous three. As long as you understand the first three, it is not difficult to understand this.


package com.example.clock; 
 
import java.util.ArrayList; 
import java.util.Timer; 
import java.util.TimerTask; 
 
import android.content.Context; 
import android.os.Handler; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.ListView; 
import android.widget.TextView; 
 
public class StopWatchView extends LinearLayout { 
 
 private TextView tvHour,tvMin,tvSec,tvMsec; 
 private Button btnStart,btnPause,btnResume,btnReset,btnLap; 
 private ListView lvTimeList; 
 private ArrayAdapter<String> adapter; 
 public StopWatchView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 } 
 
 @Override 
 protected void onFinishInflate() { 
 super.onFinishInflate(); 
  
 tvHour = (TextView) findViewById(R.id.timeHour); 
 tvHour.setText("0"); 
 tvMin = (TextView) findViewById(R.id.timeMin); 
 tvMin.setText("0"); 
 tvSec = (TextView) findViewById(R.id.timeSec); 
 tvSec.setText("0"); 
 tvMsec = (TextView) findViewById(R.id.timeMsec); 
 tvMsec.setText("0"); 
  
 btnStart = (Button) findViewById(R.id.btnSWStart); 
 btnPause = (Button) findViewById(R.id.btnSWPause); 
 btnResume = (Button) findViewById(R.id.btnSWResume); 
 btnLap = (Button) findViewById(R.id.btnSWLap); 
 btnReset = (Button) findViewById(R.id.btnSWReset); 
  
 btnStart.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  startTimer(); 
  btnStart.setVisibility(View.GONE); 
  btnPause.setVisibility(View.VISIBLE); 
  btnLap.setVisibility(View.VISIBLE); 
  } 
 }); 
 btnPause.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  stopTimer(); 
  btnPause.setVisibility(View.GONE); 
  btnResume.setVisibility(View.VISIBLE); 
  btnLap.setVisibility(View.GONE); 
  btnReset.setVisibility(View.VISIBLE); 
  } 
 }); 
 btnResume.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  startTimer(); 
  btnResume.setVisibility(View.GONE); 
  btnPause.setVisibility(View.VISIBLE); 
  btnLap.setVisibility(View.VISIBLE); 
  btnReset.setVisibility(View.GONE); 
  } 
 }); 
 btnReset.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  stopTimer(); 
  tenMSecs = 0; 
  adapter.clear(); 
  btnReset.setVisibility(View.GONE); 
  btnLap.setVisibility(View.GONE); 
  btnPause.setVisibility(View.GONE); 
  btnResume.setVisibility(View.GONE); 
  btnStart.setVisibility(View.VISIBLE); 
  } 
 }); 
 btnLap.setOnClickListener(new OnClickListener() { 
  
  @Override 
  public void onClick(View v) { 
  adapter.insert(String.format("%d:%d:%d.%d", tenMSecs/100/60/60,tenMSecs/100/60%60,tenMSecs/100%60,tenMSecs%100), 0); 
  } 
 }); 
 btnLap.setVisibility(View.GONE); 
 btnPause.setVisibility(View.GONE); 
 btnResume.setVisibility(View.GONE); 
 btnReset.setVisibility(View.GONE); 
  
 lvTimeList = (ListView) findViewById(R.id.lvWatchTime); 
 adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1); 
 lvTimeList.setAdapter(adapter); 
  
 showTimerTask = new TimerTask() { 
  
  @Override 
  public void run() { 
  handle.sendEmptyMessage(MSG_WHAT_SHOW_TIME); 
  } 
 }; 
 timer.schedule(showTimerTask, 200, 200); 
 } 
 
 private void startTimer(){ 
 if (timerTask == null) { 
  timerTask = new TimerTask() { 
   
  @Override 
  public void run() { 
   tenMSecs++; 
  } 
  }; 
  timer.schedule(timerTask, 10, 10); 
 } 
 } 
 private void stopTimer(){ 
 if (timerTask != null) { 
  timerTask.cancel(); 
  timerTask = null; 
 } 
 } 
 
 private int tenMSecs = 0; 
 private Timer timer =new Timer(); 
 private TimerTask timerTask = null; 
 private TimerTask showTimerTask = null; 
 private static final int MSG_WHAT_SHOW_TIME = 1; 
 
 private Handler handle = new Handler(){ 
 public void handleMessage(android.os.Message msg) { 
  switch (msg.what) { 
  case MSG_WHAT_SHOW_TIME: 
  tvHour.setText(tenMSecs/100/60/60+""); 
  tvMin.setText(tenMSecs/100/60%60+""); 
  tvSec.setText(tenMSecs/100%60+""); 
  tvMsec.setText(tenMSecs%100+""); 
  break; 
 
  default: 
  break; 
  } 
 }; 
 }; 
 public void onDestroy() { 
 timer.cancel(); 
 } 
 
} 

So far, my first actual combat is completed, but the interface is very low, which only realizes the basic functions, but it has not been greatly improved on the interface, and will be improved slowly in the actual combat afterwards.

Source code download: Android multifunctional clock


Related articles: