上一篇为大家介绍的是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 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 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(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 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(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多功能时钟源代码,Android多功能时钟开发案例(实战篇)相关推荐

  1. C# Xamarin For Android移动开发项目实战篇

    一.课程介绍 在前面阿笨的<C# Xamarin移动开发基础进修篇>课程中,大家已经熟悉和了解了Xamarin移动App开发的基础知识和原理.本次分享课<C# Xamarin移动开发 ...

  2. android获取通知栏消息源代码,Android高仿UC浏览器和360手机卫士消息常驻栏(通知栏)(示例代码)...

    之前网上看了下自己定义消息栏,通知栏,了解到了Notification这个控件.发现UC浏览器等都是这样的类型,今天写个demo实现下.如图: 当中每一个button都有不同的功能.代码例如以下: p ...

  3. java模拟时钟源代码_Android实现模拟时钟(简单+漂亮)--时针、分针、秒针

    前言 前不久在网上看见Android实现的模拟时钟,感觉十分有意思,这里是地址: 秒表.笔者突然对其有了兴趣,也想去实现以下自己的模拟时钟.折腾了一阵子总算是弄出来了 现在将实现方式共享出来,大家一些 ...

  4. Android开发系列——实战篇5:自适应屏幕尺寸(超详细教程)

    在实战篇4中构建了界面之后,在模拟器中完好的布局,在实际下载到手机上的时候,却出现了布局不协调的问题. 在模拟器Nexus6上的布局界面: 在真机HUWEI P10 Plus上的布局界面: 在真机HU ...

  5. Android Study Jam 在线答疑第三期:Jetpack Compose 案例实战

    Android Study Jam 火热进行中 感兴趣的小伙伴都上车了吗? 为助力大家打好 Jetpack Compose 基础 我们的第三场 Office Hours 在线答疑 将于 今天上午 10 ...

  6. android锁机病毒源代码,Android 锁机样本母体分析

    本帖最后由 莫问刀 于 2018-8-17 09:49 编辑 --------------------------------------------------------------------- ...

  7. android 防误触 源代码,Android Launcher 解决BubbleTextView 点击事件只在ICON上面触发,防止误触...

    思路比较简单: 在OnTouch手指抬起的时候,进行判断. //是不是触摸在图标上面 public boolean getRectTouchIcon(MotionEvent event){ if(ge ...

  8. Android开发系列——实战篇11:多线程与异步机制

    本文介绍安卓的多线程与异步任务处理的机制 目录 一.多线程 1.主线程与子线程 2.Handler用法详解 使用Handler发送post请求 使用Handler处理Message消息 一.多线程 1 ...

  9. 【android免root脚本制作】总览Auto.js开发小结——基础篇

    Auto.js是什么 Auto.js是一款写脚本,ui界面,运行脚本,制作简单安卓app的一体式软件.并且是全开源的免费APP,类似于按键精灵,而且本软件有全部按键精灵的功能,还有其他例如控件操作等, ...

最新文章

  1. 2021年5G发展展望
  2. jquery跟js初始化加载的多种方法及区别介绍
  3. 老男孩老师的博客地址 - 转自devops1992
  4. 跨越行业绊脚石,阿里云函数计算发布 7 大技术突破
  5. 无招胜有招之Java进阶JVM(二)
  6. Python机器学习:逻辑回归001什么是逻辑回归
  7. 董淳光SQLITE3使用总结-转
  8. linux 线程编译指令i,linux线程篇之(一):线程的创建与应用
  9. 「管理数学基础」3.4 凸分析:最优性的充要条件、无约束极小化问题、一般非线性规划问题
  10. 【从 0 开始机学习】正则化技术原理与编程!
  11. 阶段3 3.SpringMVC·_07.SSM整合案例_08.ssm整合之Spring整合MyBatis框架
  12. 【c4d学习笔记】OC渲染器安装问题
  13. 龙芯pmon 中Nand配置说明
  14. android程序 获取flash容量大小,Android用WebView加载flash大文件偶然会出现内存溢出以及蓝色打问号小方块问题的解决方案...
  15. 连接MyBatis内部SqlSession与业务接口的代理类MapperProxy
  16. win7 注册表禁 com服务器,win7系统注册表清理后导致不能上网如何解决
  17. CTF 流量分析Wireshark Certificate例题
  18. window.print() 表格打印 完美实现分页
  19. Cartopy 0.20 最新功能 —— Cartopy 装不上别慌,内附解决方案
  20. IPFS和梅克尔森林

热门文章

  1. hashlib安装报错
  2. 跟社区学laravel博客实战1
  3. deepstream python
  4. vscode下载插件让vue代码高亮
  5. office2016和365″”弹窗去除去掉方法完美解决
  6. html鼠标悬停边框变虚线,css设置表格的边框为实线还是虚线,+鼠标悬停显示提示字...
  7. iCloud 照片windows 快速备份释放空间的方案
  8. mysql,oracle数据库优化之索引
  9. oracle ora 19698,RMAN异机还原遭遇ORA-19698错误案例
  10. 内网渗透——搭建域控制器