5 主要的代码
DeskClockMainActivity.java
package com.cn.daming.deskclock;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CheckBox;
import android.widget.CursorAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class DeskClockMainActivity extends Activity implements OnItemClickListener{
static final String PREFERENCES = "AlarmClock";
/** This must be false for production. If true, turns on logging,
test code, etc. */
static final boolean DEBUG = false;
private SharedPreferences mPrefs;
private LayoutInflater mFactory;
private ListView mAlarmsList;
private Cursor mCursor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//取自定义布局的LayoutInflater
mFactory = LayoutInflater.from(this);
//取getSharedPreferences中key==“AlarmClock”的值
mPrefs = getSharedPreferences(PREFERENCES, 0);
//获取闹钟的cursor
mCursor = Alarms.getAlarmsCursor(getContentResolver());
//更新布局界面
updateLayout();
}
//加载更新界面布局
private void updateLayout() {
setContentView(R.layout.alarm_clock);
mAlarmsList = (ListView) findViewById(R.id.alarms_list);
AlarmTimeAdapter adapter = new AlarmTimeAdapter(this, mCursor);
mAlarmsList.setAdapter(adapter);
mAlarmsList.setVerticalScrollBarEnabled(true);
mAlarmsList.setOnItemClickListener(this);
mAlarmsList.setOnCreateContextMenuListener(this);
View addAlarm = findViewById(R.id.add_alarm);
addAlarm.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addNewAlarm();
}
});
// Make the entire view selected when focused.
addAlarm.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
v.setSelected(hasFocus);
}
});
ImageButton deskClock =
(ImageButton) findViewById(R.id.desk_clock_button);
deskClock.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
}
private void addNewAlarm() {
startActivity(new Intent(this, SetAlarm.class));
}
/**
* listview的适配器继承CursorAdapter
* @author wangxianming
* 也可以使用BaseAdapter
*/
private class AlarmTimeAdapter extends CursorAdapter {
public AlarmTimeAdapter(Context context, Cursor cursor) {
super(context, cursor);
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
DigitalClock digitalClock =
(DigitalClock) ret.findViewById(R.id.digitalClock);
digitalClock.setLive(false);
return ret;
}
//把view绑定cursor的每一项
public void bindView(View view, Context context, Cursor cursor) {
final Alarm alarm = new Alarm(cursor);
View indicator = view.findViewById(R.id.indicator);
// Set the initial resource for the bar image.
final ImageView barOnOff =
(ImageView) indicator.findViewById(R.id.bar_onoff);
barOnOff.setImageResource(alarm.enabled ?
R.drawable.ic_indicator_on : R.drawable.ic_indicator_off);
// Set the initial state of the clock "checkbox"
final CheckBox clockOnOff =
(CheckBox) indicator.findViewById(R.id.clock_onoff);
clockOnOff.setChecked(alarm.enabled);
// Clicking outside the "checkbox" should also change the state.
//对checkbox设置监听,使里外一致
indicator.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
clockOnOff.toggle();
updateIndicatorAndAlarm(clockOnOff.isChecked(),
barOnOff, alarm);
}
});
DigitalClock digitalClock =
(DigitalClock) view.findViewById(R.id.digitalClock);
// set the alarm text
final Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, alarm.hour);
c.set(Calendar.MINUTE, alarm.minutes);
digitalClock.updateTime(c);
digitalClock.setTypeface(Typeface.DEFAULT);
// Set the repeat text or leave it blank if it does not repeat.
TextView daysOfWeekView =
(TextView) digitalClock.findViewById(R.id.daysOfWeek);
final String daysOfWeekStr =
alarm.daysOfWeek.toString(DeskClockMainActivity.this, false);
if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
daysOfWeekView.setText(daysOfWeekStr);
daysOfWeekView.setVisibility(View.VISIBLE);
} else {
daysOfWeekView.setVisibility(View.GONE);
}
// Display the label
TextView labelView =
(TextView) view.findViewById(R.id.label);
if (alarm.label != null && alarm.label.length() != 0) {
labelView.setText(alarm.label);
labelView.setVisibility(View.VISIBLE);
} else {
labelView.setVisibility(View.GONE);
}
}
};
//更新checkbox
private void updateIndicatorAndAlarm(boolean enabled, ImageView bar,
Alarm alarm) {
bar.setImageResource(enabled ? R.drawable.ic_indicator_on
: R.drawable.ic_indicator_off);
Alarms.enableAlarm(this, alarm.id, enabled);
if (enabled) {
SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
alarm.daysOfWeek);
}
}
/*
* (non-Javadoc)
* @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
* 创建上下文菜单
*/
@Override
public boolean onContextItemSelected(final MenuItem item) {
final AdapterContextMenuInfo info =
(AdapterContextMenuInfo) item.getMenuInfo();
final int id = (int) info.id;
// Error check just in case.
if (id == -1) {
return super.onContextItemSelected(item);
}
switch (item.getItemId()) {
case R.id.delete_alarm:
// Confirm that the alarm will be deleted.
new AlertDialog.Builder(this)
.setTitle(getString(R.string.delete_alarm))
.setMessage(getString(R.string.delete_alarm_confirm))
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d,
int w) {
Alarms.deleteAlarm(DeskClockMainActivity.this, id);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
return true;
case R.id.enable_alarm:
final Cursor c = (Cursor) mAlarmsList.getAdapter()
.getItem(info.position);
final Alarm alarm = new Alarm(c);
Alarms.enableAlarm(this, alarm.id, !alarm.enabled);
if (!alarm.enabled) {
SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
alarm.daysOfWeek);
}
return true;
case R.id.edit_alarm:
Intent intent = new Intent(this, SetAlarm.class);
intent.putExtra(Alarms.ALARM_ID, id);
startActivity(intent);
return true;
default:
break;
}
return super.onContextItemSelected(item);
}
/*
* (non-Javadoc)
* @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
* 创建菜单
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View view,
ContextMenuInfo menuInfo) {
// Inflate the menu from xml.
getMenuInflater().inflate(R.menu.context_menu, menu);
// Use the current item to create a custom view for the header.
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
final Cursor c =
(Cursor) mAlarmsList.getAdapter().getItem((int) info.position);
final Alarm alarm = new Alarm(c);
// Construct the Calendar to compute the time.
final Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, alarm.hour);
cal.set(Calendar.MINUTE, alarm.minutes);
final String time = Alarms.formatTime(this, cal);
// Inflate the custom view and set each TextView's text.
final View v = mFactory.inflate(R.layout.context_menu_header, null);
TextView textView = (TextView) v.findViewById(R.id.header_time);
textView.setText(time);
textView = (TextView) v.findViewById(R.id.header_label);
textView.setText(alarm.label);
// Set the custom view on the menu.
menu.setHeaderView(v);
// Change the text based on the state of the alarm.
if (alarm.enabled) {
menu.findItem(R.id.enable_alarm).setTitle(R.string.disable_alarm);
}
}
/*
* (non-Javadoc)
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
* 设置菜单的点击事件的处理
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_settings:
startActivity(new Intent(this, SettingsActivity.class));
return true;
case R.id.menu_item_desk_clock:
//modify by wangxianming in 2012-4-14
// startActivity(new Intent(this, DeskClock.class));
return true;
case R.id.menu_item_add_alarm:
addNewAlarm();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
/*
* (non-Javadoc)
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
* 创建菜单
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.alarm_list_menu, menu);
return super.onCreateOptionsMenu(menu);
}
/*
* (non-Javadoc)
* @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
* 创建菜单的点击事件响应
*/
public void onItemClick(AdapterView<?> adapterView, View v, int pos, long id) {
Intent intent = new Intent(this, SetAlarm.class);
intent.putExtra(Alarms.ALARM_ID, (int) id);
startActivity(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
ToastMaster.cancelToast();
mCursor.close();
}
}
DontPressWithParentLayout.java
package com.cn.daming.deskclock;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
/**
* Special class to to allow the parent to be pressed without being pressed
* itself. This way the time in the alarm list can be pressed without changing
* the background of the indicator.
*/
public class DontPressWithParentLayout extends LinearLayout {
public DontPressWithParentLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setPressed(boolean pressed) {
// If the parent is pressed, do not set to pressed.
if (pressed && ((View) getParent()).isPressed()) {
return;
}
super.setPressed(pressed);
}
}
RepeatPreference.java
package com.cn.daming.deskclock;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.ListPreference;
import android.util.AttributeSet;
import java.text.DateFormatSymbols;
import java.util.Calendar;
public class RepeatPreference extends ListPreference {
// Initial value that can be set with the values saved in the database.
private Alarm.DaysOfWeek mDaysOfWeek = new Alarm.DaysOfWeek(0);
// New value that will be set if a positive result comes back from the
// dialog.
private Alarm.DaysOfWeek mNewDaysOfWeek = new Alarm.DaysOfWeek(0);
public RepeatPreference(Context context, AttributeSet attrs) {
super(context, attrs);
String[] weekdays = new DateFormatSymbols().getWeekdays();
String[] values = new String[] {
weekdays[Calendar.MONDAY],
weekdays[Calendar.TUESDAY],
weekdays[Calendar.WEDNESDAY],
weekdays[Calendar.THURSDAY],
weekdays[Calendar.FRIDAY],
weekdays[Calendar.SATURDAY],
weekdays[Calendar.SUNDAY],
};
setEntries(values);
setEntryValues(values);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
mDaysOfWeek.set(mNewDaysOfWeek);
setSummary(mDaysOfWeek.toString(getContext(), true));
callChangeListener(mDaysOfWeek);
}
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
builder.setMultiChoiceItems(
entries, mDaysOfWeek.getBooleanArray(),
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
mNewDaysOfWeek.set(which, isChecked);
}
});
}
public void setDaysOfWeek(Alarm.DaysOfWeek dow) {
mDaysOfWeek.set(dow);
mNewDaysOfWeek.set(dow);
setSummary(dow.toString(getContext(), true));
}
public Alarm.DaysOfWeek getDaysOfWeek() {
return mDaysOfWeek;
}
}
alarm_alert.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center">
- <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center_horizontal" android:background="@drawable/dialog" android:orientation="vertical">
<TextView android:id="@+id/alertTitle" style="?android:attr/textAppearanceLarge" android:padding="5dip" android:singleLine="true" android:ellipsize="end" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" />
<ImageView android:layout_width="match_parent" android:layout_height="1dip" android:scaleType="fitXY" android:gravity="fill_horizontal" android:src="@drawable/dialog_divider_horizontal_light" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" />
- <com.cn.daming.deskclock.DigitalClock style="@style/clock" android:paddingTop="30dip" android:paddingBottom="30dip" android:baselineAligned="true" android:gravity="center_horizontal">
<TextView android:id="@+id/timeDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="64sp" android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/am_pm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="?android:attr/textColorPrimary" />
</com.cn.daming.deskclock.DigitalClock>
- <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" style="@android:style/ButtonBar">
<Button android:id="@+id/snooze" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:text="@string/alarm_alert_snooze_text" />
- <!--
blank stretchable view
-->
<View android:layout_width="2dip" android:layout_height="2dip" android:layout_gravity="fill_horizontal" android:layout_weight="1" />
<Button android:id="@+id/dismiss" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:text="@string/alarm_alert_dismiss_text" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
alarm_clock.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/base_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFB7DD" android:orientation="vertical">
- <LinearLayout android:id="@+id/add_alarm" android:clickable="true" android:focusable="true" android:background="@android:drawable/list_selector_background" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<ImageView style="@style/alarm_list_left_column" android:duplicateParentState="true" android:gravity="center" android:scaleType="center" android:src="@drawable/add_alarm" />
<TextView android:duplicateParentState="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="?android:attr/textColorPrimary" android:text="@string/add_alarm" />
</LinearLayout>
<ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:gravity="fill_horizontal" android:src="@android:drawable/divider_horizontal_dark" />
<ListView android:id="@+id/alarms_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" />
- <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<ImageButton android:id="@+id/desk_clock_button" style="@style/ButtonStripLeft" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_clock_strip_desk_clock" android:contentDescription="@string/desk_clock_button_description" />
- <com.cn.daming.deskclock.DigitalClock style="@style/ButtonStripRight" android:layout_width="match_parent" android:layout_height="match_parent">
- <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:baselineAligned="true">
<TextView android:id="@+id/timeDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="6dip" android:textSize="45sp" android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/am_pm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
</com.cn.daming.deskclock.DigitalClock>
</LinearLayout>
</LinearLayout>
alarm_time.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
- <!--
I can't use a normal checkbox here for a couple reasons:
1. The checkbox button resources cannot contain layouts so I have to
use 2 views for the clock and the bar.
2. The normal checkbox has a really messed up layout. Using the button
attribute produces a left-aligned image that has some kind of
minimum height. If the bar is a checkbox, it is too tall and is
clipped on the right.
-->
- <com.cn.daming.deskclock.DontPressWithParentLayout android:id="@+id/indicator" style="@style/alarm_list_left_column" android:background="@drawable/clock_selector" android:gravity="center" android:orientation="vertical">
<CheckBox android:id="@+id/clock_onoff" android:focusable="false" android:clickable="false" android:background="@drawable/indicator_clock_onoff" android:duplicateParentState="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center" android:button="@null" />
<ImageView android:id="@+id/bar_onoff" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingTop="4dip" android:src="@drawable/ic_indicator_off" />
</com.cn.daming.deskclock.DontPressWithParentLayout>
- <!--
note by wangxianming android:background="?android:attr/windowBackground"
-->
<ImageView android:src="@drawable/divider_vertical_dark" android:layout_width="wrap_content" android:layout_height="match_parent" android:paddingTop="4dip" android:paddingBottom="4dip" android:scaleType="fitXY" android:gravity="fill_vertical" />
- <!--
A layout that displays the time. Shows time, am/pm (if 12-hour),
and an optional line below, used for day/days of week
-->
- <com.cn.daming.deskclock.DigitalClock android:id="@+id/digitalClock" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:layout_weight="1" android:orientation="vertical" android:paddingLeft="16dip" android:paddingRight="16dip">
- <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:baselineAligned="true">
<TextView android:id="@+id/timeDisplay" android:includeFontPadding="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="6dip" android:textSize="28sp" android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/am_pm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:textStyle="bold" android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:paddingLeft="8dip" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorTertiary" android:textStyle="bold" android:gravity="right" android:singleLine="true" />
</LinearLayout>
<TextView android:id="@+id/daysOfWeek" android:includeFontPadding="false" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorSecondary" />
</com.cn.daming.deskclock.DigitalClock>
</LinearLayout>
以上代码实现的功能主要包括获取安卓设备的当前时间、进行定时(24时制)、输入备忘录内容、到达定时时间铃声提醒、选择闹钟响铃周期、增删备忘录等功能。以下是实现后的各部分功能的图片展示以及设计的应用的图标:
6 软件的提升空间
经过五个阶段的开发,慧版备忘录并没有成为一个完善、成熟的软件当前的备忘录只能说是具备了一些最基本的功能,和那些商用的备忘录软件比起来还有很大的差距,因此仍然还有非常巨大的发挥空间来对它进行完善。
比如说以下功能是可以考虑加入到慧版备忘录中的:
1. 增加设置选项,让用户选择自己心仪的页面的背景;
2. 优化软件界面,提供更多备忘录相关的功能;
3. 设计更为精细化的闹钟定时设计,比如以年或月作为定时的时间段;
4. 美化软件图标以及增加相应的进入动画等;
7 实验总结
这是移动开发的综合试验其中涉及了本学期学到的大部分内容,在设计时有部分内容因遗忘所以无法实现,后来通过百度以及询问同学,总算是实现了预期的功能。通过这次试验对移动技术开发有了综合性的认识,也取得了一定运用能力,同时也是对自己的一次检验。相信这次试验对以后的学习会有很大的帮助。