本文实例为大家分享了Android实战闹钟项目的具体代码,供大家参考,具体内容如下
一、闹钟功能的介绍以及界面的展示
该闹钟是根据我们手机闹钟设计的一个简单的闹钟APP,其中包含时钟、闹钟、秒表和计时器功能。用户可以对闹钟添加和删除,可以对秒表计时、暂停和重置,对计时器可以暂停、计时、继续和重置等功能。
二、介绍系统的设计界面
闹钟的布局文件代码如下
由于该闹钟系统包含时钟、闹钟、计时器、秒表四个功能,所以只要在xml文件插入TabHost控件就能实现在手机上更加简洁地展示四个功能。后面只需要在TabHost中插入四个Tab用来切换展示的界面,具体的代码实现如下:
public class MainActivity extends AppCompatActivity {
private TabHost mTabHost;
private StopWatchView mStopWatchView;
@Override
public SharedPreferences getPreferences(int mode) {
return super.getPreferences(mode);
}
@RequiresApi(api = Build.VERSION_CODES.P)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabHost = (TabHost) findViewById(R.id.tabhost);
mTabHost.setup();
mTabHost.addTab(mTabHost.newTabSpec("tabTime").setIndicator("时钟").setContent(R.id.tabTime));
mTabHost.addTab(mTabHost.newTabSpec("tabAlarm").setIndicator("闹钟").setContent(R.id.tabAlarm));
mTabHost.addTab(mTabHost.newTabSpec("tabTimer").setIndicator("计时器").setContent(R.id.tabTimer));
mTabHost.addTab(mTabHost.newTabSpec("tabStopWatch").setIndicator("秒表").setContent(R.id.tabStopWatch));
mStopWatchView = (StopWatchView) findViewById(R.id.tabStopWatch);
}
@Override
protected void onDestroy() {
super.onDestroy();
mStopWatchView.onDestory();
}
}
一、时钟功能
因为时钟功能中,只要显示当前的日期和时钟就可以了,所以只需要插入一个TextView用来显示日期时间就可以了。
xml文件中的代码(new 一个时钟类TimeView,把时钟一块的LinearLayout换成com.example.tsclock.TimeView)
// 时钟
<com.example.tsclock.TimeView
android:id="@+id/tabTime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tvTime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center"/>
</com.example.tsclock.TimeView>
TimeView.java
要将时间显示到TabHost中,就必须先要获取其中的id,然后通过Calendar获取当前系统的时间,最后再每过1秒钟刷新一次,这样就能够再TextView中出现时间在不停的变化。
public class TimeView extends LinearLayout {
private TextView tvTime;
public TimeView(Context context) {
super(context);
}
public TimeView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public TimeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// 在初始化之后进行的操作
@Override
protected void onFinishInflate() {
super.onFinishInflate();
tvTime = (TextView) findViewById(R.id.tvTime);
// handler每秒执行一次
timerHandler.sendEmptyMessage(0);
}
// 可见属性发生变化之后
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (visibility == View.VISIBLE){ // 如果可见 则发送一个消息
timerHandler.sendEmptyMessage(0);
}else{ // 如果不可见 移除所有的消息
timerHandler.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 timerHandler = new Handler() {
public void handleMessage(android.os.Message msg){
// 呈现出来
refreshTime();
// 如果可见 则刷新
if (getVisibility() == View.VISIBLE){
// 1000毫秒之后再制学校handlerMessage()方法
timerHandler.sendEmptyMessageDelayed(0,1000);
}
}
};
}
二、闹钟功能
闹钟功能就相对时钟功能就复杂很多了,因为这里需要对闹钟进行增加,删除等操作,而且可能需要展示多个闹钟的时间。所以这里需要用到有一个Button控件用来增加闹钟和一个ListView控件用来展示闹钟的时间。
xml代码
// 闹钟
<com.example.tsclock.AlarmView
android:id="@+id/tabAlarm"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/lvAlarmList"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
</ListView>
<Button
android:id="@+id/btnAddAlarm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/add_alarm"
android:textColor="#FFFFFF"
android:background="@color/colorBlue" />
</com.example.tsclock.AlarmView>
闹钟类,AlarmView.java
需要判断时间到了需要触发事件,需要播放音乐和震动。所以播放音乐和震动放在另一个活动中(PlayAlarmAty.java )
public class AlarmView extends LinearLayout {
private Button btnAddAlarm;
private ListView lvAlarmList;
private ArrayAdapter<AlarmData> mAdapter;
private static final String KEY_ALARM_LIST = "alarmList";
// 使用系统的闹钟服务
private AlarmManager mAlarmManager;
public AlarmView(Context context) {
super(context);
init();
}
public AlarmView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
// 使用闹钟服务设定闹钟
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
}
// 在初始化之后进行的操作
@Override
protected void onFinishInflate() {
super.onFinishInflate();
btnAddAlarm = (Button)findViewById(R.id.btnAddAlarm);
lvAlarmList = (ListView) findViewById(R.id.lvAlarmList);
// 系统的简单资源
mAdapter = new ArrayAdapter<AlarmView.AlarmData>(getContext(),android.R.layout.simple_list_item_1);
// 设置Adapter
lvAlarmList.setAdapter(mAdapter);
// 读取已经存储在SharedPreferences中的数据
readSavedAlarmList();
btnAddAlarm.setOnClickListener(new View.OnClickListener() {// 添加闹钟的点击事件
@Override
public void onClick(View v) {
addAlarm();
}
});
// 删除闹钟
lvAlarmList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,final int position, long id) {
new AlertDialog.Builder(getContext()).setTitle("操作选项").setItems(new CharSequence[]{"删除"}, 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 = mAdapter.getItem(position);
// 把闹钟从闹钟列表移除
mAdapter.remove(ad);
saveAlarmList();
// 移除闹钟
mAlarmManager.cancel(PendingIntent.getBroadcast(getContext(),ad.getId(),new Intent(getContext(),AlarmReceiver.class),0));
}
// 添加闹钟
private void addAlarm(){
// 获取当前时间
Calendar c = Calendar.getInstance();
// 弹出一个时间的选择框
new TimePickerDialog(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 (calendar.getTimeInMillis() <= currentTime.getTimeInMillis()){
calendar.setTimeInMillis(calendar.getTimeInMillis()+24*60*60*1000);
}
AlarmData ad = new AlarmData(calendar.getTimeInMillis());
mAdapter.add(ad);
//需要根据API版本来判断调用,从Android4.4(API19)开始,为了节能省电(减少系统唤醒和电池使用)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManager.setWindow(AlarmManager.RTC_WAKEUP,
ad.getTime(),
100, // 时间误差范围 100毫秒
PendingIntent.getBroadcast(getContext(), ad.getId(),
new Intent(getContext(), AlarmReceiver.class), 0));
} else {
mAlarmManager.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();
}
// 存储数据(存到SharedPreferences中)
private void saveAlarmList(){
SharedPreferences.Editor editor = getContext().getSharedPreferences(AlarmView.class.getName(),Context.MODE_PRIVATE).edit();
// 存储数据(for循环遍历Adapter)
StringBuffer sb = new StringBuffer();
//getCount表示这个adapter里面有多少item,就是有多少闹钟
for (int i = 0 ; i < mAdapter.getCount(); i++){
sb.append(mAdapter.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 readSavedAlarmList(){
// 获取到SharedPreferences(数据内容)
SharedPreferences sp = getContext().getSharedPreferences(AlarmView.class.getName(),Context.MODE_PRIVATE);
String content = sp.getString(KEY_ALARM_LIST,null);
// 这里需要判断,不然没闹钟数据的时候会有空指针异常
if (content != null){
//这里取得每一个闹钟的time添加到数组里
String[] timeStrings = content.split(",");
// 遍历数组,把数据添加到mAdapter
for (String string : timeStrings){
mAdapter.add(new AlarmData(Long.parseLong(string)));
}
}
}
//闹钟的数据,用一个类要保存,这是常用的做法
private static class AlarmData{
private long time = 0;
private String timeLabel = ""; // 在外界获取时间的标签的字符串
private Calendar date;
// 闹钟响起的时间
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 AlarmData(String ad){
this.timeLabel = ad;
}
public void setTime(long time){
this.time = time;
}
public long getTime(){
return time;
}
public void setTimeLable(String timeLable){
this.timeLabel = timeLable;
}
@Override
public String toString() {
return getTimeLabel();
}
public String getTimeLabel() {
return timeLabel;
}
//为了给每一个闹钟设定一个标识,方便取消闹钟的使用能知道是哪一个闹钟
public int getId(){
return (int) (getTime()/1000/60);
}
}
}
当触发事件发生时,我们就要播放我们之前准备的音乐了,但是怎么播放呢,这里我们就要用到mediaPlayer媒体播放器这个函数了,这个函数主要就是用来播放音乐或者动画等。当开始播放时,我们也需要弹出警告框,提醒用户去关闭闹钟,所以这里我们需要另外编写一个类,用来执行这些功能。
PlayAlarmAty类中有播放音乐,开启震动,弹出关闭闹钟的dialog。
public class PlayAlarmAty extends Activity {
// 音乐播放器
private MediaPlayer mMediaPlayer;
private Vibrator vibrator;
private PowerManager.WakeLock mWakelock;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // hide title
Window win = getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
winParams.flags |= (WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
// 播放闹钟铃声
mMediaPlayer = MediaPlayer.create(this,R.raw.music); //使用create方式,创建MediaPlayer对象
mMediaPlayer.setLooping(true); // 设置是否对播放的音乐进行循环播放
mMediaPlayer.start();
startVibrator();
createDialog();
}
@Override
protected void onPause() {
super.onPause();
finish();
// 释放锁屏
releaseWakeLock();
}
@Override
protected void onResume() {
super.onResume();
// 唤醒屏幕
acquireWakeLock();
}
@Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.stop();
mMediaPlayer.release(); // 释放掉
}
// 唤醒屏幕
private void acquireWakeLock() {
if (mWakelock == null) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakelock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.SCREEN_DIM_WAKE_LOCK, this.getClass()
.getCanonicalName());
mWakelock.acquire();
}
}
// 释放锁屏
private void releaseWakeLock() {
if (mWakelock != null && mWakelock.isHeld()) {
mWakelock.release();
mWakelock = null;
}
}
// 震动
private void startVibrator() {
// 想设置震动大小可以通过改变pattern来设定,如果开启时间太短,震动效果可能感觉不到
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = { 500, 1000, 500, 1000 }; // 停止 开启 停止 开启
vibrator.vibrate(pattern, 0);
}
private void createDialog() {
new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_clock)
.setTitle("闹钟")
.setMessage("闹钟时间到了!!!")
.setPositiveButton("推迟10分钟", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
tenMRemind();
mMediaPlayer.stop();
vibrator.cancel();
finish();
}
})
.setNegativeButton("关闭", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mMediaPlayer.stop();
vibrator.cancel();
finish();
}
}).create().show();
}
// 推迟10分钟提醒
private void tenMRemind(){
//设置时间
Calendar calendar_now = Calendar.getInstance();
calendar_now.setTimeInMillis(System.currentTimeMillis());
calendar_now.set(Calendar.HOUR_OF_DAY, calendar_now.get(Calendar.HOUR_OF_DAY));
calendar_now.set(Calendar.MINUTE, calendar_now.get(Calendar.MINUTE)+10);
calendar_now.set(Calendar.SECOND, 0);
calendar_now.set(Calendar.MILLISECOND, 0);
//时间选择好了
Intent intent = new Intent(this, AlarmReceiver.class);
//注册闹钟广播
PendingIntent sender = PendingIntent.getBroadcast(
this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am;
am = (AlarmManager) this.getSystemService(this.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar_now.getTimeInMillis(), sender);
}
}
但是要当时间到了启动这个活动,就需要一个接收器,接受这个事件,所以有需要另一个类AlarmReceiver。
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
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); // 要启动的类
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 设置启动的模式
context.startActivity(i);
}
}
三、秒表功能
秒表功能包含四个功能键,分别为开始,暂停、继续和重置。所以需要四个Button,然后需要三个EditText分别用来给用户输入时分秒。具体的xml代码如下:
// 秒表
<com.example.tsclock.StopWatchView
android:id="@+id/tabStopWatch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/timeHour"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:id="@+id/timeMin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:id="@+id/timeSec"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="."
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:id="@+id/timeMSec"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>
<ListView
android:id="@+id/lvWatchTime"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnSWStart"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/start"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnSWPause"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/pause"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnSWResume"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/resume"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnSWLap"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/lap"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnSWReset"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/reset"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
</LinearLayout>
</com.example.tsclock.StopWatchView>
在秒表功能中,含有四个Button,但是有时候只要显示一个或者是两个其余的就需要隐藏,所以这里就需要用到Button中的属性setVisibility(View.GONE)或者是setVisibility(View.VISIBLE),这是用来隐藏和显示Button。
有时候我们需要考虑系统的健壮性,比如当我们输入大于59的数或者是小于0的数,这时候我们需要系统检测出来,并进行修正。
需要注意的就是,当我们修改计时的时间的时候,当我们不小心将数目清空的时候,这时候就会将空指针上传,导致系统的崩溃,所以我们需要判断是不是空指针,防止越界报错。
该秒表功能有五个Button,所以需要对每个Button添加触发事件,其实startTime()函数的功能为开始计时,stopTime()函数的功能为暂停计时。所以这里需要弄清楚的就是什么时候该让那些按钮隐藏,什么时候该让那些按钮显示。
public class StopWatchView extends LinearLayout {
private TextView tvHour,tvMin,tvSec,tvMSec;
private Button btnSWStart,btnSWResume,btnSWReset,btnSWLap,btnSWPause;
private ListView lvTimeList;
private ArrayAdapter<String> adapter;
private Timer mTimer = new Timer();
private TimerTask mTimerTask = null;
private int tenMSec = 0;
private TimerTask showTimerTask = null;
private static final int MSG_WHAT_SHOW_TIME = 1;
public StopWatchView(Context context, @Nullable 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");
// 计时
btnSWLap = (Button) findViewById(R.id.btnSWLap);
btnSWLap.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 时 分 秒 毫秒
adapter.insert(String.format("%d:%d:%d.%d",tenMSec/100/60/60,tenMSec/100/60%60,tenMSec/100%60,tenMSec%100),0);
}
});
// 开始
btnSWStart = (Button) findViewById(R.id.btnSWStart);
btnSWStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startTimer();
btnSWStart.setVisibility(View.GONE);
btnSWPause.setVisibility(View.VISIBLE);
btnSWLap.setVisibility(View.VISIBLE);
}
});
// 暂停
btnSWPause = (Button) findViewById(R.id.btnSWPause);
btnSWPause.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopTimer();
btnSWPause.setVisibility(View.GONE);
btnSWResume.setVisibility(View.VISIBLE);
btnSWLap.setVisibility(View.GONE);
btnSWReset.setVisibility(View.VISIBLE);
}
});
// 继续
btnSWResume = (Button) findViewById(R.id.btnSWResume);
btnSWResume.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startTimer();
btnSWResume.setVisibility(View.GONE);
btnSWPause.setVisibility(View.VISIBLE);
btnSWReset.setVisibility(View.GONE);
btnSWLap.setVisibility(View.VISIBLE);
}
});
// 重置
btnSWReset = (Button) findViewById(R.id.btnSWReset);
btnSWReset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopTimer();
tenMSec = 0;
adapter.clear();// 重置需要清除列表
btnSWLap.setVisibility(View.GONE);
btnSWPause.setVisibility(View.GONE);
btnSWResume.setVisibility(View.GONE);
btnSWReset.setVisibility(View.GONE);
btnSWStart.setVisibility(View.VISIBLE);
}
});
// 设置除了开始之外 其它四个按钮不可见
btnSWLap.setVisibility(View.GONE);
btnSWPause.setVisibility(View.GONE);
btnSWResume.setVisibility(View.GONE);
btnSWReset.setVisibility(View.GONE);
lvTimeList = (ListView) findViewById(R.id.lvWatchTime);
// 初始化话adapter
adapter = new ArrayAdapter<String>(getContext(),android.R.layout.simple_list_item_1);
lvTimeList.setAdapter(adapter);
// 使用showTimerTask不断执行刷新的操作
showTimerTask = new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(MSG_WHAT_SHOW_TIME);
}
};
mTimer.schedule(showTimerTask,200,200); // 一秒钟刷新五次
}
private void startTimer(){
if (mTimerTask == null){
mTimerTask = new TimerTask() {// 计时的timerTask
@Override
public void run() {
tenMSec++;
}
};
mTimer.schedule(mTimerTask,10,10); // 每隔十毫秒执行一次
}
}
private void stopTimer(){
if (mTimerTask != null){
mTimerTask.cancel();
mTimerTask = null;
}
}
// 呈现时间的handler
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MSG_WHAT_SHOW_TIME:
tvHour.setText(tenMSec/100/60/60+""); // 时
tvMin.setText(tenMSec/100/60%60+""); // 分
tvSec.setText(tenMSec/100%60+""); // 秒
tvMSec.setText(tenMSec%100+""); // 毫秒
break;
default:
break;
}
}
};
public void onDestory() {
mTimer.cancel();
}
}
四、计时器功能
这个和上面讲了秒表比较类似,不同的是多一个Button按钮用来计时,还多一个EditView(毫秒值),另外还需要一个ListView用来显示计时的时间,详细的xml代码如下:
// 计时器
<com.example.tsclock.TimerView
android:id="@+id/tabTimer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<EditText
android:id="@+id/etHour"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<EditText
android:id="@+id/etMin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<EditText
android:id="@+id/etSec"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>
<LinearLayout
android:id="@+id/btnGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnStart"
android:layout_width="0dp"
android:text="@string/start"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnPause"
android:layout_width="0dp"
android:text="@string/pause"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnResume"
android:layout_width="0dp"
android:text="@string/resume"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
<Button
android:id="@+id/btnReset"
android:layout_width="0dp"
android:text="@string/reset"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:background="@color/colorBlue"/>
</LinearLayout>
</com.example.tsclock.TimerView>
计时器功能和秒表功能差不多
public class TimerView extends LinearLayout {
private Button btnStart,btnPause,btnResume,btnReset;
private EditText etHour,etMin,etSec;
private Timer mTimer = new Timer(); // 计时器
private TimerTask mTimerTask = null;
private int allTimerCount = 0;
private static final int MSG_WHAT_TIME_IS_UP = 1;
private static final int MSG_WHAT_TIME_IS_TICK = 2; // 时钟一格一格的往下走
private ListView mListView;
public TimerView(Context context) {
super(context);
}
public TimerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//开始
btnStart = (Button) findViewById(R.id.btnStart);
btnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startTimer();
btnStart.setVisibility(View.GONE);
btnPause.setVisibility(View.VISIBLE);
btnReset.setVisibility(View.VISIBLE);
etHour.setEnabled(false);
etMin.setEnabled(false);
etSec.setEnabled(false);
}
});
// 暂停
btnPause = (Button) findViewById(R.id.btnPause);
btnPause.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopTimer();
btnPause.setVisibility(View.GONE);
btnResume.setVisibility(View.VISIBLE);
}
});
// 继续
btnResume = (Button) findViewById(R.id.btnResume);
btnResume.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startTimer();
btnResume.setVisibility(View.GONE);
btnPause.setVisibility(View.VISIBLE);
}
});
// 重置
btnReset = (Button) findViewById(R.id.btnReset);
btnReset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopTimer();
etHour.setText("00");
etMin.setText("00");
etSec.setText("00");
etHour.setEnabled(true);
etMin.setEnabled(true);
etSec.setEnabled(true);
btnStart.setVisibility(View.VISIBLE);
btnPause.setVisibility(View.GONE);
btnResume.setVisibility(View.GONE);
btnReset.setVisibility(View.GONE);
}
});
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) {
if (!TextUtils.isEmpty(s)){
int value = Integer.parseInt(s.toString());
if (value > 59){
etHour.setText("59");
}else if (value < 0){
etHour.setText("0");
}
}
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("0");
}
}
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("0");
}
}
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 (mTimerTask == null){
// 所使用时间的计数
allTimerCount = Integer.parseInt(etHour.getText().toString())*60*60+Integer.parseInt(etMin.getText().toString())*60+Integer.parseInt(etSec.getText().toString());
mTimerTask = new TimerTask() {
@Override
public void run() { // run方法会被mTimer执行
// 每执行一次 计数减一
allTimerCount--;
// 获取到当
mHandler.sendEmptyMessage(MSG_WHAT_TIME_IS_TICK);
if (allTimerCount <= 0){
// 访问mHandler
mHandler.sendEmptyMessage(MSG_WHAT_TIME_IS_UP);
stopTimer();
}
}
};
mTimer.schedule(mTimerTask,1000,1000); // run方法每隔一秒执行一次
}
}
private void stopTimer(){
if (mTimerTask != null){
mTimerTask.cancel();
mTimerTask = null;
}
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MSG_WHAT_TIME_IS_TICK:
int hour = allTimerCount/60/60;
int min = (allTimerCount/60)%60;
int sec = allTimerCount%60;
etHour.setText(hour+"");
etMin.setText(min+"");
etSec.setText(sec+"");
break;
case MSG_WHAT_TIME_IS_UP:
// 执行弹出对话框操作
// 把时间停止(弹出一个对话框)
new AlertDialog.Builder(getContext()).setTitle("时间到了!!!").setNegativeButton("退出",null).show();
btnPause.setVisibility(View.GONE);
btnResume.setVisibility(View.GONE);
btnReset.setVisibility(View.GONE);
btnStart.setVisibility(View.VISIBLE);
etHour.setEnabled(true);
etMin.setEnabled(true);
etSec.setEnabled(true);
break;
default:
break;
}
}
};
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。