Android多功能时钟开发案例(实战篇)

上一篇为大家介绍的是Android多功能时钟开发基础内容,大家可以回顾一下,Android多功能时钟开发案例(基础篇)

接下来进入实战,快点来学习吧。

一、时钟
在布局文件中我们看到,界面上只有一个TextView,这个TextView的作用就是显示一个系统的当前时间,同时这个时间还是一秒一秒跳的,要实现一秒一秒的跳就需要我们每隔一秒就要刷新一下,同时我们这里还考虑了切换到另一个Tab的时候,这个时间就不跳动了,这样就会减少这个对系统的占用,考虑到了这点我们在这里用到了Handler,通过handler发送的msg.what 来判断是否要刷新时间。

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);
  //当再次切换到这个Tab时我们就再发送一次这个消息,否者就把所有的消息移除掉
  if (visibility == View.VISIBLE) {
   timeHandler.sendEmptyMessage(0);
  }else{
   timeHandler.removeMessages(0);
  }
 } 

 private void refreshTime(){
  //获取当前的时间
  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(); 

   //处于当前Tab的时候给自己发送信息,可以刷新
   if (getVisibility() == View.VISIBLE) {
    //1秒钟后再次执行以下sendEmptyMessage,what参数用于区分不同的message
    timeHandler.sendEmptyMessageDelayed(0, 1000);
   }
  };
 };
}

其实这里的Handler可以用Timer来完成亦可以达到同样的效果。
在这里要提一下的是onFinishInflate(),这在我们自定义布局的时候一定要用到的,解释以及例子在之后上传的知识点中同样有,看看那个就可以了。
二、闹钟
从第二个布局中我们可以看到,我们在这里用到了一个ListView,这是用来存储我们添加的闹钟的,既然这里用到了ListView,那么我们接着就会想到要给这个ListView一个适配器adapter,因此我们会在这里创建这么一个适配器,
private ArrayAdapter<AlarmData> adapter; 
看到这里可能又会有疑问了,AlarmData这是个什么东西?有这么一个数据类型吗??其实这里我们自定义了一个数据类型,用来专门存储一下创建的闹钟时间。我们来看一下自定义的数据类型代码吧!

// 自定义数据类型
 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月%d日 %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();
  } 

 }

这个数据类型的代码其实还是很容易明白的,不多讲了。
当我们到这里的时候,我们其实还没有真正的完成,假如我们的代码已经写好了,并且可以运行了我们运行一次后,并且添加了N个闹钟,当我们退出程序,再次打开就会发现,我们之前创建的闹钟都没了,原因是我们虽然把数据临时的保存在了ListView中,但是我们并没有长时间的保存,因此我们接着就来讲讲长久的保存这些闹钟数据。

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)));
   }
  }
 }

上面的一些陌生的类型在之后的知识点中可以查看。

接着我们来看看最关键的就是添加闹钟

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();
 }

这里我们可以看到TPDiolog这个,当你自己尝试过后可能也会遇到同样的问题,那就是当你通过TimePickerDialog这个系统的时间选择控件的时候,点击确定后,会创建两条记录,这是因为我们点击确定后会调用该事件监听器的时间,在关闭这个Dialog的时候也会调用一次,所以我们在这里自己重写了一下该类的方法

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);
 } 

 //重写该方法是为了避免调用两次onTimeSet
 @Override
 protected void onStop() {
  //super.onStop();
 }
}

在之前的代码中我们还看到了一个alarmManager这一对象,这是我们为了调用系统的闹钟服务创建的实例,我们也因此而创建了一个AlarmReceiver.class

public class AlarmReceiver extends BroadcastReceiver { 

 @Override
 public void onReceive(Context context, Intent arg1) {
  System.out.println("闹钟执行了!"); 

  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);
  //设置intent的启动模式
  i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  context.startActivity(i);
 } 

}

一些小的地方讲好了,最后把AlarmView.class的完整代码贴上。

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();
   }
  });
  // 长按某项删除
  lvListAlarm.setOnItemLongClickListener(new OnItemLongClickListener() { 

   @Override
   public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
     final int position, long arg3) { 

    new AlertDialog.Builder(getContext())
      .setTitle("操作选项")
      .setItems(new CharSequence[] { "删除", "删除1" },
        new DialogInterface.OnClickListener() { 

         @Override
         public void onClick(DialogInterface dialog,
           int which) {
          switch (which) {
          case 0:
           deleteAlarm(position);
           break; 

          default:
           break;
          }
         }
        }).setNegativeButton("取消", 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)));
   }
  }
 } 

 // 自定义数据类型
 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月%d日 %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();
  } 

 }
}

三、计时器
计时器的主要功能就是你先设定一个时间,然后点击开始,时间就会一秒一秒的减少,在这里我么主要用到了Timer这个系统的计时器,这代码中没有上面难懂的地方,有些地方已经给上注释了,所以直接贴代码,可能有些人会不知道Timer怎么用,之后的知识点中都会有提到。

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) {
    /*
     * 这个方法是在Text改变过程中触发调用的, 它的意思就是说在原有的文本s中,
     * 从start开始的count个字符替换长度为before的旧文本,
     * 注意这里没有将要之类的字眼,也就是说一句执行了替换动作。
     */
    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; 

}

四、秒表
最后的秒表相信大家都不陌生,用到的知识正好之前的三个都有讲到,只要明白前三个后,这个就不难理解了。

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();
 } 

}

到此为止,自己的第一个实战算是完成了,但是就是界面很low,这个只是把基本的功能实现了,但是在界面上没有做很大的完善,在之后的实战中会慢慢改进的。

源码下载:Android多功能时钟

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android获取设备CPU核数、时钟频率以及内存大小的方法

    本文实例讲述了Android获取设备CPU核数.时钟频率以及内存大小的方法.分享给大家供大家参考,具体如下: 因项目需要,分析了一下 Facebook 的开源项目 - Device Year Class. Device Year Class 的主要功能是根据 CPU核数.时钟频率 以及 内存大小 对设备进行分级.代码很简单,只包含两个类: DeviceInfo -> 获取设备参数, YearClass -> 根据参数进行分级. 下表是 Facebook 公司提供的分级标准,其中 Year 栏表

  • Android多功能时钟开发案例(基础篇)

    本文我们进入Android多功能时钟开发实战学习,具体的效果可以参考手机上的时钟,内容如下 首先我们来看一看布局文件layout_main.xml 整个布局: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" androi

  • Android实现简单时钟View的方法

    通过Canvas的平移与旋转简化绘图逻辑是一个非常有用的技巧,下面的时钟view就是利用这个方法完成的,省去了使用三角函数计算坐标的麻烦. package com.example.swt369.simpleclock; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; i

  • android实现widget时钟示例分享

    一.在 AndroidManifest.xml文件中配置Widgets: 复制代码 代码如下: <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.widget"    android:versionCode="1"    android:versionName="1.0" >   

  • Android ActionBar制作时钟实例解析

    本文实例为大家分享了Android ActionBar制作时钟的具体代码,供大家参考,具体内容如下 1. MainActivity.java   package com.example.days19actionbar07custom; import com.example.days19actionbar07custom.R; import android.app.Activity; import android.os.Bundle; import android.view.Menu; impor

  • Android 仿日历翻页、仿htc时钟翻页、数字翻页切换效果

    废话不多说,效果图: 自定义控件找自网络,使用相对简单,具体还没有来得及深入研究,只是先用笨方法大概实现了想要的效果,后续有空会仔细研究再更新文章, 本demo切换方法是用的笨方法,也就是由新数字和旧数字相比较来切换数字变换的,大致使用方法如下: //获取输入框中的数字 int newNumber = Integer.parseInt(etInput.getText().toString()); //获取个.十.百位数字 int nbai = newNumber / 100; int nshi

  • Android通过Path实现搜索按钮和时钟复杂效果

    在Android中复杂的图形的绘制绝大多数是通过path来实现,比如绘制一条曲线,然后让一个物体随着这个曲线运动,比如搜索按钮,比如一个简单时钟的实现: 那么什么是path呢! 定义:path  就是路径,就是图形的路径的集合,它里边包含了路径里边的坐标点,等等的属性.我们可以获取到任意点的坐标,正切值. 那么要获取Path上边所有点的坐标还需要用到一个类,PathMeasure; PathMesure: PathMeasure是一个用来测量Path的类,主要有以下方法: 构造方法 公共方法 可

  • android高仿小米时钟(使用Camera和Matrix实现3D效果)

    继续练习自定义View..毕竟熟才能生巧.一直觉得小米的时钟很精美,那这次就搞它~这次除了练习自定义View,还涉及到使用Camera和Matrix实现3D效果. 一个这样的效果,在绘制的时候最好选择一个方向一步一步的绘制,这里我选择由外到内.由深到浅的方向来绘制,代码步骤如下: 1.首先老一套~新建attrs.xml文件,编写自定义属性如时钟背景色.亮色(用于分针.秒针.渐变终止色).暗色(圆弧.刻度线.时针.渐变起始色),新建MiClockView继承View,重写构造方法,获取自定义属性值

  • Android仿小米时钟效果

    我在一个[博客] android高仿小米时钟(使用Camera和Matrix实现3D效果)上面看到了小米时钟实现.特别感兴趣.就认真的看了一遍.并自己敲了一遍.下面说下我自己的理解和我的一些改进的地方效果真的特别棒就发布了自己的时钟应用. 先上图(电脑没有gif截图软件.大家凑合看.哪个软件好也可以给我推荐下) 话不多说,首先自定义控件XimiClockView继承view  并做一些初始化的操作 看到的漂亮时钟图片我自己画的效果图(以后妈妈再也不用担心我迟到了) public XimiCloc

  • Android画个时钟玩玩

    先看下最终的效果 开始实现 新建一个ClockView集成View public class ClockView extends View { } 先重写onMeasure方法,这里要先说一下View的测量模式,一共有三种: 1.EXACTLY 即精确值模式,当我们将控件的layout_width属性或layout_height属性指定为具体数值时,比如android:layout_width="100dp",或者指定为math_parent属性时(占据父View的大小),系统使用的是

随机推荐