<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文範例為大家分享了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; } } }; }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45