編輯:關於Android編程
學習了快一學期的Android了,之前的知識點都是零散的學習的,只有當我們真正的去把他們用起來的時候才會發現難點,自己才會獨立嘗試去解決某個問題。接下來是我的一個簡單的多功能時鐘的小實戰(視頻資源http://pan.baidu.com/s/1i5AT4nN 密碼:jq7g)
具體的效果可以參考手機上的時鐘。首先我們來看一看布局文件layout_main.xml
我們總的來看一下整個布局
<framelayout android:id="@+id/container" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout> <framelayout android:id="@android:id/tabcontent" android:layout_height="match_parent" android:layout_width="match_parent"> …… …… …… </framelayout>
整個布局整的是一個FrameLayout,我們在裡面放了一個TabHost,接下來我們就可以在裡面直接添加自己想要的布局了,可能初學者初一看會有那麼一個疑問,就是
這是完整的布局文件代碼
<framelayout android:id="@+id/container" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout> <framelayout android:id="@android:id/tabcontent" android:layout_height="match_parent" android:layout_width="match_parent"> </framelayout>
講完了布局,我們來講講MainActivity
private TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tabHost = (TabHost) findViewById(android.R.id.tabhost); tabHost.setup(); // 為TabHost添加標簽 // 新建一個newTabSpec(newTabSpec)用來指定該標簽的id(就是用來區分標簽)的 // 設置其標簽和圖表(setIndicator) // 設置內容(setContent) /* * 設置選項卡 : -- 設置按鈕名稱 : setIndicator(時鐘); -- 設置選項卡內容 : setContent(), * 可以設置視圖組件, 可以設置Activity, 也可以設置Fragement; */ 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)); }
在MainActivity中主要的操作就是設置TabHost,上面的代碼中已經貼上了解釋,這裡就不講了,接著我們就重點來講講時鐘、鬧鐘、計時器和秒表這四部分。
在布局文件中我們看到,界面上只有一個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 //可以參考 該網址http://www.68idc.cn/help/buildlang/ask/20150206210559.html @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); } }
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 ArrayAdapteradapter; 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開發者應該使用FlatBuffers替代JSON》,嚇得我趕緊看了看,突然感覺自己用了好長時間的JSON解析似乎落伍了
最近工作需要做一款直播APP,恩是的,從RTMP協議的實現開始到處理服務器高並發、負載均衡、客戶端播放器實現等等等.....估計全部寫完我也到而立之年了吧23333...
本節引言: 本節給大家帶來基礎UI控件部分的最後一個控件:DrawerLayout,官方給我們提供的一個側滑菜單 控件,和上一節的ViewPage
Android系統中一個應用程序的主題是由ActivityThread構成的。不過涉及到很多細節如ActivityThread是由誰來創建的 又是在什麼時間創建?它和系統
一、問題現象1、多次進出需要強制橫屏的app,比如Real FootBa