Android开发实战闹钟项目
本文实例为大家分享了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;
}
}
};
}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。
看完文章,还可以扫描下面的二维码下载快手极速版领4元红包
除了扫码领红包之外,大家还可以在快手极速版做签到,看视频,做任务,参与抽奖,邀请好友赚钱)。
邀请两个好友奖最高196元,如下图所示:







