編輯:關於Android編程
這次是一個時鐘類應用,目前依舊是主要的功能,長得還是很挫。當然了,核心功能是有的……
布局的話,不管是采用FrameLayout或者LinearLayout都可以。
我這裡采用了FrameLayout,然後加上一個TabHost,之前在論壇看到有同學提問在WF中這種多個欄目的用什麼控件,我的答案是在WF、WPF、Windows App、ASP.NET以及安卓上都是Tab開頭的控件。
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" tools:context=".MainActivity" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<framelayout android:id="@android:id/tabcontent" android:layout_height="match_parent" android:layout_width="match_parent">
</framelayout>
</framelayout>
定義好了TabHost之後就可以在MainAcitivity類中實例化它們了。
private static TabHost tabHost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = (TabHost)findViewById(R.id.tabHost);
tabHost.setup();
tabHost.addTab(tabHost.newTabSpec(tabAlarm).
setIndicator(鬧鐘).setContent(R.id.tabAlarm));
tabHost.addTab(tabHost.newTabSpec(tabTime).
setIndicator(時鐘).setContent(R.id.tabTime));
tabHost.addTab(tabHost.newTabSpec(tabTimer).
setIndicator(計時器).setContent(R.id.tabTimer));
tabHost.addTab(tabHost.newTabSpec(tabStopWatch).
setIndicator(秒表).setContent(R.id.tabStopWatch));
}
如果你想調整“鬧鐘”與“時鐘”這些的先後順序,直接在代碼中調整代碼執行順序即可。
首先呢,別的不管,我為大家准備了非常好聽的鈴聲,可惜鈴聲只能放源碼裡而不能放博客上……
現在來寫一個AlarmView類,到時候在布局文件中可以直接使用它。
AlarmView類應該擴展LinearLayout,因為前面說到的,AlarmView是用作布局的。
private AlarmManager alarmManager;
public AlarmView(Context context) {
super(context);
init();
}
public AlarmView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AlarmView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
alarmManager = (AlarmManager)getContext().getSystemService(Context.ALARM_SERVICE);
}
實例化一個鬧鐘管理類,後面就通過它來使用鬧鐘服務。
核心部分都在這裡了,注釋都加了,大家慢慢看吧:
@Override
protected void onFinishInflate(){
super.onFinishInflate();
// 實例化按鈕和列表
btnAddAlarm = (Button)findViewById(R.id.btnAddAlarm);
lvAlarmList = (ListView)findViewById(R.id.lvAlarmList);
// 實例化適配器
adapter = new ArrayAdapter(getContext(),
android.R.layout.simple_list_item_1);
// 為列表添加適配器
lvAlarmList.setAdapter(adapter);
// 保存鬧鐘列表
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:
// 對話框中的項索引從0開始,刪除選中項
deleteAlarm(position);
break;
case 1:
// 刪除所有項,實際App中並不常用,只是因為測試過程中添加了太多鬧鐘。
deleteAllAlarm();
break;
default:
break;
}
}
}
).setNegativeButton(取消, null).show(); // 為對話框添加一個取消的按鈕
return true;
}
});
}
上面用到的addAlarm方法,這裡也列出來了。注意彈出的時間選擇對話框會因安卓系統版本而不同,我GIF中的是Android 5.0的。
// 添加鬧鐘
private void addAlarm(){
// 實例化一個Calendar類,並取當前時間
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類
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 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, content);
System.out.println(content); // 調試使用
}else{ // 如果長度為空,也要提交一個空的上去
editor.putString(KEY_ALARM, null);
}
// 記得提交
editor.commit();
}
應用不能每次關掉後數據就沒有了,需要將它們保存起來,因此也需要能夠加載保存的數據。
// 讀取保存的鬧鐘列表,在每次加載應用的時候會調用它
private void readSavedAlarmList(){
// 實例化共享首選項
SharedPreferences sp = getContext().getSharedPreferences(
AlarmView.class.getName(), Context.MODE_PRIVATE);
String content = sp.getString(KEY_ALARM, null);
if(content != null){
String[] timeStrings = content.split(,);
// 遍歷每一個字符串,並將其添加到適配器中
for(String str : timeStrings){
adapter.add(new AlarmData(Long.parseLong(str)));
}
}
}
刪除鬧鐘的方法,重點在於:1,在AlarmManager中取消鬧鐘;2,不能在
// 刪除鬧鐘,傳入一個position位置,刪除指定項
private void deleteAlarm(int position){
// 根據傳入的位置參數實例化一個AlarmData
AlarmData ad = adapter.getItem(position);
// 從適配器中移除
adapter.remove(ad);
// 刪除後記得再次保存列表
saveAlarmList();
// 記得在鬧鐘管理中將其取消掉,否則刪除後鬧鐘依舊會激活
alarmManager.cancel(PendingIntent.getBroadcast(getContext(),ad.getId(),
new Intent(getContext(), AlarmReceiver.class),0));
}
// 刪除所有鬧鐘
private void deleteAllAlarm(){
// 獲取適配器中的鬧鐘數量
int adapterCount =adapter.getCount(); // 為adapter的個數進行計數
AlarmData ad;
// 因為每次刪除後適配器的數量都會改變,所以需要在上面一次性計算好,不能將其放到for循環中計算
for(int i = 0; i < adapterCount; i++){
// 此處括號中不能填i,因為每次移除後第二項又變成第一項
ad = adapter.getItem(0); // 每次從第1個開始移除
adapter.remove(ad);
saveAlarmList(); // 移除後重新保存列表
alarmManager.cancel(PendingIntent.getBroadcast(getContext(),ad.getId(),
new Intent(getContext(),AlarmReceiver.class),0)); // 取消鬧鐘的廣播
}
}
最後就要設置一個AlarmData類,其中設置方法獲取鬧鐘的請求碼。
private static class AlarmData{
private String timeLabel = ;
private long time = 0;
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 long getTime(){
return time;
}
public String getTimeLabel(){
return timeLabel;
}
// 設置唯一的請求碼
public int getId(){
return (int)(getTime()/1000/60);
}
// 重載頭String()方法
@Override
public String toString(){
return getTimeLabel();
}
}
現在來寫一個PlayAlarmAty類,它得擴展自Activity。
private MediaPlayer mp;
Button btnAlarmPause;
Button btnAlarmReset;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm_player_aty);
mp = MediaPlayer.create(this,R.raw.ringtone);
mp.start();
btnAlarmPause = (Button)findViewById(R.id.btnAlarmPause);
btnAlarmPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onPause();
}
});
btnAlarmReset = (Button)findViewById(R.id.btnAlarmReset);
btnAlarmReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDestroy();
}
});
}
@Override
protected void onPause() {
super.onPause();
mp.pause();
mp.release();
}
@Override
protected void onDestroy() {
super.onDestroy();
mp.stop();
mp.release();
}
其對應的布局是:
這是在鬧鐘激活是需要彈出的界面,所以你需要一個接收器。
AlarmReceiver類需要擴展自BroadcastReceiver,重載onReceive方法:
@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,啟動該Activity
Intent i = new Intent(context, PlayAlarmAty.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
別放了在清單文件中添加它們……(在application下)
哦對了,忘了說,需要用到的string都放在strings.xml,這個就不貼出來了。
因為還是比較長的,所以就分成3篇來寫好了。
准備的鈴聲挺好聽的,至少比代碼好聽,哈哈……不管是需要鈴聲還是需要代碼的,直接評論留郵箱吧,我就不上傳到CSDN資源了。代碼會繼續更新的,注釋也會繼續更新……
項目也上傳到Github了,歡迎大家貢獻代碼啊——傳送門 。
華為榮耀87月19日上午10點08分,榮耀8將在線上線下同步開賣。很多華為手機的粉絲們都在等待,華為榮耀8真的配置是怎麼樣的呢?下文就讓小編給大家介紹華為榮
在開發java工程時,一個項目可能分為多個模塊,為了實現模塊間的解耦和獨立,提高模塊的復用性,通常將項目按模塊分為多個java工程進行開發,最後通過jar包等工
叨了個叨最近因為換工作的一些瑣事搞的我一個頭兩個大,也沒怎麼去學新東西,實在是有些愧疚。新項目用到了EventBus3.0,原來只是聽說EventBus的鼎鼎大名,一直沒
前言在Android開發中,消息推送功能的使用非常常見。為了降低開發成本,使用第三方推送是現今較為流行的解決方案。今天,我將手把手教大家如何在你的應用裡集成小米推送目錄1