多功能时钟应用
2016-04-05 11:25
555 查看
近几天做了个多功能时钟,分享一下
主界面
对应的代码:
MainActivity.java
对应代码:
TabAlarm.java
里面还有一个BroadcastReceiver需要注册
以及重写的MyTimePickerDialog.java
TabTimer.java
TabStopWatch.java
这里需要用到工具类
最后贴一些资源和布局文件吧:
main.xml
strings.xml
arrays.xml
主界面
对应的代码:
MainActivity.java
package com.example.clock; import android.app.Activity; import android.os.Bundle; import android.widget.TabHost; public class MainActivity extends Activity { private TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = (TabHost) findViewById(android.R.id.tabhost); tabHost.setup(); // Call setup() before adding tabs if loading TabHost using // findViewById(). // However: You do not need to call setup() after getTabHost() in // TabActivity. tabHost.addTab(tabHost.newTabSpec("tabTime").setIndicator("时钟") .setContent(R.id.tabTime)); tabHost.addTab(tabHost.newTabSpec("tabAlarm").setIndicator("闹钟") .setContent(R.id.tabAlarm)); tabHost.addTab(tabHost.newTabSpec("tabTimer").setIndicator("计时器") .setContent(R.id.tabTimer)); tabHost.addTab(tabHost.newTabSpec("tabStopWatch").setIndicator("秒表") .setContent(R.id.tabStopWatch)); } }
时钟界面
TabTime.javapackage com.example.clock; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.widget.LinearLayout; import android.widget.TextView; //tabtime就显示系统时间,注释部分表示是否在当前页面,如果在就发送message,不在就不发送 //有没有其实无所谓 public class TabTime extends LinearLayout { private TextView tvTime; private Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { tvTime.setText(new SimpleDateFormat("HH:mm:ss", Locale.CHINA) .format(new Date())); //if (getVisibility() == View.VISIBLE) { myHandler.sendEmptyMessage(0); //} } }; public TabTime(Context context) { super(context); } public TabTime(Context context, AttributeSet attrs) { super(context, attrs); } public TabTime(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onFinishInflate() { super.onFinishInflate(); tvTime = (TextView) findViewById(R.id.tvTime); myHandler.sendEmptyMessage(0); } // @Override // protected void onVisibilityChanged(View changedView, int visibility) { // super.onVisibilityChanged(changedView, visibility); // // if (visibility == View.VISIBLE) { // myHandler.sendEmptyMessage(0); // } else { // myHandler.removeMessages(0); // } // } }
闹钟界面:
对应代码:
TabAlarm.java
package com.example.clock; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import android.app.AlarmManager; import android.app.AlertDialog; import android.app.PendingIntent; 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.os.SystemClock; import android.util.AttributeSet; import android.util.Log; 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.TimePicker; import com.example.clock.tool.AlarmReceiver; import com.example.clock.tool.MyTimePickerDialog; //闹钟功能 public class TabAlarm extends LinearLayout { private Button btn_add; private ListView listView; // 自定义数据类型用于adapter private class AlarmData { private long time; private Date date; public AlarmData(long time) { this.time = time; date = new Date(time); } public long getTime() { return time; } public String getTimeLabel() { return new SimpleDateFormat("MM-dd HH:mm", Locale.CHINA) .format(date); } @Override public String toString() { return getTimeLabel(); } }; private ArrayAdapter<AlarmData> adapter; private AlarmManager alarmManager; public TabAlarm(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public TabAlarm(Context context, AttributeSet attrs) { super(context, attrs); init(); } public TabAlarm(Context context) { super(context); init(); } private void init() { alarmManager = (AlarmManager) getContext().getSystemService( Context.ALARM_SERVICE); } @Override protected void onFinishInflate() { super.onFinishInflate(); btn_add = (Button) findViewById(R.id.btn_add); listView = (ListView) findViewById(R.id.lvAlarmList); adapter = new ArrayAdapter<TabAlarm.AlarmData>(getContext(), android.R.layout.simple_list_item_1); listView.setAdapter(adapter); readAlarmList(); btn_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addAlarm(); } }); // btn用来增加闹钟,listview的长按事件用来删除闹钟 listView.setOnItemLongClickListener(new 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: adapter.remove(adapter .getItem(position)); saveAlarmList(); break; } } }).setNegativeButton("取消", null).show(); return true; } }); } private void addAlarm() { Calendar calendar = Calendar.getInstance(); new MyTimePickerDialog(getContext(), new OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, hourOfDay); c.set(Calendar.MINUTE, minute); Calendar currentCalendar = Calendar.getInstance(); if (c.getTimeInMillis() <= currentCalendar.getTimeInMillis()) { c.setTimeInMillis(currentCalendar.getTimeInMillis() + 24 * 60 * 60 * 1000); } adapter.add(new AlarmData(c.getTimeInMillis())); saveAlarmList(); // 使用TimePickerDialog时,点击对话框的确定按钮,会添加两条数据, // 原因是OnTimeSetListener中的onTimeSet()执行了两次, // 点击确定按钮时执行一次, // 对话框取消时,TimePickerDialog的onStop()方法中也执行了一次。 // 解决方法:重写TimePickerDialog类,并覆盖onStop() // 在com.example.clock.tool包中 alarmManager.setExact(AlarmManager.RTC_WAKEUP, SystemClock .elapsedRealtime(), PendingIntent.getBroadcast( getContext(), 0, new Intent(getContext(), AlarmReceiver.class), 0)); // setRepeating在API19以后不再准确,我试了好多种组合都不行 } }, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), true).show(); } private void saveAlarmList() { Editor editor = getContext().getSharedPreferences( TabAlarm.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(","); }//每条记录用逗号隔开 String content = ""; if (!sb.toString().equals("")) { content = sb.toString().substring(0, sb.length() - 1); } editor.putString("AlarmList", content); Log.i("record", content); editor.commit(); } private void readAlarmList() { SharedPreferences sp = getContext().getSharedPreferences( TabAlarm.class.getName(), Context.MODE_PRIVATE); String content = sp.getString("AlarmList", null); if (!content.equals("")) { String[] timeString = content.split(","); for (String string : timeString) { adapter.add(new AlarmData(Long.parseLong(string))); } } } }
里面还有一个BroadcastReceiver需要注册
package com.example.clock.tool; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "闹铃响了", Toast.LENGTH_SHORT).show(); } }
以及重写的MyTimePickerDialog.java
package com.example.clock.tool; import android.app.TimePickerDialog; import android.content.Context; public class MyTimePickerDialog extends TimePickerDialog { public MyTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, callBack, hourOfDay, minute, is24HourView); } public MyTimePickerDialog(Context context, int theme, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, theme, callBack, hourOfDay, minute, is24HourView); } @Override protected void onStop() { // 注释掉,防止onTimeSet()执行两次 // super.onStop(); } }
计时器界面
TabTimer.java
package com.example.clock; import android.content.Context; import android.os.CountDownTimer; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; //计时器功能 public class TabTimer extends LinearLayout { private Spinner spinner; private TextView tv; private ArrayAdapter<CharSequence> adapter; private long tempMillis, defaultMillis; private Button btn1, btn2; private MyCount mCount; public TabTimer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public TabTimer(Context context, AttributeSet attrs) { super(context, attrs); } public TabTimer(Context context) { super(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); tv = (TextView) findViewById(R.id.tvShowTime); btn1 = (Button) findViewById(R.id.button1); btn2 = (Button) findViewById(R.id.button2); spinner = (Spinner) findViewById(R.id.spinner1); adapter = ArrayAdapter.createFromResource(getContext(), R.array.time, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); final long[] arrayTime = {30*1000, 1*60*1000, 2*60*1000, 5*60*1000}; spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { tempMillis = arrayTime[pos]; defaultMillis = tempMillis; } @Override public void onNothingSelected(AdapterView<?> parent) { tempMillis = arrayTime[0];// 默认30s defaultMillis = tempMillis; } }); //spinner获取时间,后面两个button操作整个自定义计时器 //逻辑虽然简单,但比较复杂。我调试了好一会儿 btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (btn1.getText().toString() .equals(getResources().getString(R.string.start))) { //点击开始按钮 mCount = new MyCount(tempMillis, 1000); mCount.start(); btn2.setEnabled(true); btn1.setText(getResources().getString(R.string.quit)); } else if (btn1.getText().toString() .equals(getResources().getString(R.string.quit))) { //点击取消按钮 mCount.cancel(); btn2.setEnabled(false); btn1.setText(getResources().getString(R.string.start)); tv.setText(""); btn2.setText(getResources().getString(R.string.pause)); tempMillis = defaultMillis; } } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (btn2.getText().toString() .equals(getResources().getString(R.string.pause))) { //点击暂停按钮 mCount.cancel(); btn2.setText(getResources().getString(R.string.continu)); } else if (btn2.getText().toString() .equals(getResources().getString(R.string.continu))) { //点击继续按钮 btn2.setText(getResources().getString(R.string.pause)); mCount = new MyCount(tempMillis, 1000); mCount.start(); } } }); } //自定义计时器。网上说cancel失效,但我试了一下可行 //用法比较简单,网上或者API上都有 class MyCount extends CountDownTimer { public MyCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onFinish() { tv.setText("计时结束!"); } @Override public void onTick(long millisUntilFinished) { tv.setText("剩余" + millisUntilFinished / 1000 + "秒。。。"); tempMillis = millisUntilFinished; } } }
秒表界面:
TabStopWatch.java
package com.example.clock; import android.content.Context; import android.os.Handler; import android.os.Message; 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; import com.example.clock.tool.MyDataFormat; //秒表功能 //网上的方法大多只有精确到秒,显然精度不够 //而且都是用的sendMessageDelayed方法,可能会不准 //我用的是系统时间,然后加以转化 public class TabStopWatch extends LinearLayout { private Button btn_start, btn_reset; private TextView single, total; private ListView timeCount; private ArrayAdapter<String> adapter; private long single_start, total_start; private int count;// adapter中的显示条目的计数器 private boolean isReset, isPause;// 是否重置和暂停 public TabStopWatch(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public TabStopWatch(Context context, AttributeSet attrs) { super(context, attrs); } public TabStopWatch(Context context) { super(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); single = (TextView) findViewById(R.id.single); total = (TextView) findViewById(R.id.total); btn_start = (Button) findViewById(R.id.btn_start); btn_reset = (Button) findViewById(R.id.btn_reset); timeCount = (ListView) findViewById(R.id.timeCount); adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1); timeCount.setAdapter(adapter); single.setText("00:00.00"); total.setText("00:00.00"); btn_start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (btn_start.getText().toString() .equals(getResources().getString(R.string.start))) { // 点击开始按钮 isReset = false; isPause = false; count = 0; btn_start.setText(getResources().getString(R.string.pause)); btn_reset.setEnabled(true); // 如果是第一次启动,formatLong返回0, // 如果是暂停后启动,返回的是系统时间减去textview显示的时间 single_start = System.currentTimeMillis() - MyDataFormat.formatLong(single.getText() .toString()); total_start = System.currentTimeMillis() - MyDataFormat.formatLong(total.getText() .toString()); // 获取时间 singleTextTime(); totalTextTime(); } else if (btn_start.getText().toString() .equals(getResources().getString(R.string.pause))) { // 点击停止按钮 isPause = true; btn_start.setText(getResources().getString(R.string.start)); btn_reset.setText(getResources().getString(R.string.reset)); } } }); btn_reset.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (btn_reset.getText().toString() .equals(getResources().getString(R.string.count))) { // 点击计次按钮 adapter.add("计数:" + count++ + " " + single.getText().toString()); single.setText("00:00.00"); single_start = System.currentTimeMillis(); singleTextTime(); } else if (btn_reset.getText().toString() .equals(getResources().getString(R.string.reset))) { // 点击复位按钮 adapter.clear(); single.setText("00:00.00"); total.setText("00:00.00"); btn_reset.setEnabled(false); isReset = true; btn_reset.setText(getResources().getString(R.string.count)); } } }); } private Handler myHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 1) { if (!isPause && !isReset) { single.setText(MyDataFormat.format( System.currentTimeMillis(), single_start)); myHandler.sendEmptyMessage(1); } } else if (msg.what == 2) { if (!isPause && !isReset) { total.setText(MyDataFormat.format( System.currentTimeMillis(), total_start)); myHandler.sendEmptyMessage(2); } } }; }; private void singleTextTime() { myHandler.sendEmptyMessage(1); } private void totalTextTime() { myHandler.sendEmptyMessage(2); } }
这里需要用到工具类
package com.example.clock.tool; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class MyDataFormat { // 把时间差的"00:00:000"格式变为"00:00.00" public static String format(long data, long ori) { String temp = new SimpleDateFormat("mm:ss:SSS", Locale.CHINA) .format(data - ori); int position = temp.lastIndexOf(":"); return temp.substring(0, position) + "." + temp.substring(position + 1, temp.length() - 1); } // 把string的"00:00.00"格式变为long类型 public static long formatLong(String data){ int position = data.lastIndexOf("."); data = data.substring(0, position) + ":" + data.substring(position + 1, data.length() - 1); SimpleDateFormat sdf = new SimpleDateFormat("mm:ss:SSS", Locale.CHINA); Date date = null; try { date = sdf.parse(data); } catch (ParseException e) { e.printStackTrace(); } return date.getTime(); } }
最后贴一些资源和布局文件吧:
main.xml
<LinearLayout xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.clock.MainActivity" > <TabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" > </TabWidget> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.clock.TabTime 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:gravity="center" android:textAppearance="?android:attr/textAppearanceLarge" /> </com.example.clock.TabTime> <com.example.clock.TabAlarm android:id="@+id/tabAlarm" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top|center" android:text="@string/addAlarm" /> <ListView android:id="@+id/lvAlarmList" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </com.example.clock.TabAlarm> <com.example.clock.TabTimer android:id="@+id/tabTimer" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Spinner android:id="@+id/spinner1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <TextView android:id="@+id/tvShowTime" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="false" android:gravity="center" android:textSize="30sp" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/start" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:enabled="false" android:text="@string/pause" /> </com.example.clock.TabTimer> <com.example.clock.TabStopWatch android:id="@+id/tabStopWatch" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/single" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" android:textSize="15sp" /> <TextView android:id="@+id/total" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" android:textSize="30sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/start" /> <Button android:id="@+id/btn_reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:enabled="false" android:text="@string/count" /> </LinearLayout> <ListView android:id="@+id/timeCount" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </com.example.clock.TabStopWatch> </FrameLayout> </LinearLayout> </TabHost> </LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Clock</string> <string name="addAlarm">添加闹钟</string> <string name="start">开始</string> <string name="pause">暂停</string> <string name="quit">取消</string> <string name="continu">继续</string> <string name="count">计次</string> <string name="reset">复位</string> </resources>
arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="time"> <item>30秒</item> <item>1分钟</item> <item>2分钟</item> <item>5分钟</item> </string-array> </resources>
相关文章推荐
- Java的接口和抽象类
- linux环境下集成ant+jmeter+jenkins自动化测试
- 前端效果导航汇总
- FTPUtil
- ubuntu和开发板添加启动脚本
- fullPage.js全屏滚动插件 中文帮助文档API
- 系统建设 > 医疗集团CRM系统建设步骤与分析
- eclipse手动设置jdk路径
- Tsinsen A1122 旅行家的预算
- 用户登录范例分析
- 怎么样设计良好的API
- xml 文件读取
- 携程Docker实践
- sitemesh3.0配置
- winform简单打印
- yii2
- JS基于ocanvas插件实现的简单画板效果代码(附demo源码下载)
- Javascript高级程序设计读书笔记(6)
- COOKIE和SESSION的区别
- C++统计输入字符串各个大写字母的个数