android的时钟,也就是闹钟应用,从桌面的widget直接点进去的会打开AlarmClock这个Activity.

好像我平常都不上图的,今天就上两张图先。

一张是应用界面图如下:(改天再上传了,好像今天osc服务器有问题啊)

一,初看:

总共有10个方法,加一个CursorAdapter的子类的内部类。

其中的10个方法如下:

private void updateAlarm(boolean enabled,Alarm alarm);public boolean onContextItemSelected(final MenuItem item);@Overrideprotected void onCreate(Bundle icicle);private void updateLayout();private void addNewAlarm();private void onDestory();public void onCreateContextMenu(ContextMenu menu,View view,                                ContextMenuInfo menuInfo);public boolean onOptionsItemSelected(MenuItem item);public boolean onCreateOptionsMenu(Menu menu);public void onItemClick(AdapterView parent,View v int pos,long id);

上面的方法很多都我们比较熟悉的方法吧,呵呵,那就从比较熟悉的方法开始吧。

(1) 也就是onItemClick()方法,代码如下:

 @Override    public void onItemClick(AdapterView parent, View v, int pos, long id) {        final Cursor c = (Cursor) mAlarmsList.getAdapter()                .getItem(pos);        final Alarm alarm = new Alarm(c);        Intent intent = new Intent(this, SetAlarm.class);        intent.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);        startActivity(intent);    }

AlarmClock使用一个ListView加+CursorAdapter来显示所有创建的闹钟。

当点击某一个闹钟时,它将进入到闹钟的设置界面去:

上面的代码的作用很显然,

先是所点击闹钟的对应的Cursor对象,然后

通过Alarm类的构造方法,通过Cursor构造了一个Alarm实例。

Alarm类实现了Parcle,我们可以暂时将它只想像为一个实体类,pojo之类的。

后面将详细分析,或者你现在就去看看呗。呵呵。

然后,new出了Intent,将Alarm类作为额外数据传递过去。上面还出现了Alarms类,

其实你可以暂时把Alarms类想像为Java Web开发经常用到的名字dao类,对了你就可以这样想Alarms=AlarmDao

呵呵。

然后它就启动了SetAlarm这个Activity.

好了这个方法的任务完成。

(2)onCreateOptionsMenu()方法

当你按下Menu键时,就会调用这个方法,代码如下;

@Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.alarm_list_menu, menu);        return super.onCreateOptionsMenu(menu);    }

代码很简单两行,

第一行:获得菜单构造器,然后通过R.menu.alarm_list_menu菜单资源文件构造菜单。

第二行:子类应用父类的基本实现。

默认实现中将以标准的系统菜单项来填充menu,他们被归为CATEGORY_SYSTEM组,所以他们会以应用定义菜单项正确的排列。

(3)onOptionsItemSelected()

代码如下:

    @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:                startActivity(new Intent(this, DeskClock.class));                finish();                return true;            case R.id.menu_item_add_alarm:                addNewAlarm();                return true;            case android.R.id.home:                finish();                return true;            default:                break;        }        return super.onOptionsItemSelected(item);    }

事实在应用中,按下Menu键时,只看到了[设置]这一菜单项。看下资源文件如下:

<menu xmlns:android="http://schemas.android.com/apk/res/android">    <item android:id="@+id/menu_item_add_alarm"        android:title="@string/add_alarm"        android:icon="@drawable/ic_menu_add"        android:showAsAction="always"/>    <item android:id="@+id/menu_item_settings"        android:title="@string/settings"        android:icon="@android :drawable/ic_menu_preferences"        android:showAsAction="never"/></menu>

注意到android:showAsAction=“always“

所以,这个菜单在ActionBar中显示了。

注意到 android.R.id.home这个是android4中内置的用于返回的menuItem吗?需要更多了解。

另外重要的一项R.id.menu_item_add_alarm就是添加闹钟了。它是作为ActionBar中的Action一直在显示。也是我们将主要关注的。

addNewAlarm();这个方法如下:

 private void addNewAlarm() {        startActivity(new Intent(this, SetAlarm.class)); }

简单到不能再简单了,启用闹钟设置界面。

(4)onCreateContextMenu()

ContextMenu顾名思义就是上下文菜单,在桌面应用中,我们也许叫做右键菜单。在android中一般是

通过长按来触发的菜单。

 @Override    public void onCreateContextMenu(ContextMenu menu, View view,            ContextMenuInfo menuInfo) {        // 从资源文件中上构造菜单Inflate the menu from xml.        getMenuInflater().inflate(R.menu.context_menu, menu);                 // 使用当前项来创建一个自定义view来作为头        // Use the current item to create a custom view for the header.        final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;   // 获得当前项对应Curosr,通过Cursor构造Alarm对象        final Cursor c =                (Cursor) mAlarmsList.getAdapter().getItem(info.position);        final Alarm alarm = new Alarm(c);        // 构造Calendar对象来计算时间        // 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);        // 构造自定义View,并为每一个TextView设置显示文本 。        // 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);        }    }

代码比较简单,而且我也已经在代码中注释了,也保留了原本的英文注释。呵呵,我基本只是翻译呢。

现在再把context_menu_header的布局代码贴在下面,以让大家加深理解:

<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:paddingTop="6dip"    android:paddingBottom="9dip"    android:paddingLeft="10dip"    android:paddingRight="10dip">    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="top"        android:paddingTop="6dip"        android:paddingRight="10dip"        android:src="@drawable/ic_dialog_time"/>    <TextView android:id="@+id/header_time"        style="?android:attr/textAppearanceLarge"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:singleLine="true"        android:gravity="center_vertical"        android:ellipsize="none"/>    <TextView android:id="@+id/header_label"        style="?android:attr/textAppearanceLarge"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_marginLeft="20dip"        android:singleLine="true"        android:gravity="right|center_vertical"        android:ellipsize="end"/></LinearLayout>

(5)这一个自然就是,onContextItemSelected

代码如下有点长,但是还算比较清晰吧:

 @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(AlarmClock.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: {                final Cursor c = (Cursor) mAlarmsList.getAdapter()                        .getItem(info.position);                final Alarm alarm = new Alarm(c);                Intent intent = new Intent(this, SetAlarm.class);                intent.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);                startActivity(intent);                return true;            }            default:                break;        }        return super.onContextItemSelected(item);    }

首先是从菜单项对象中获得AdapterContextMenuInfo类对象实例info

然后通过这个info获得Alarm实例id

然后做了个以防万一的错误检查。

接着对item的id值做了switch.

情况1 :用户选择了删除此闹钟

弹出一个对话框,让用户确定是否删除。如果用户确定删除。

调用Alarms.deleteAlarm(context,id)删除。

情况2:用户选择了启用/停用闹钟

通过info获得position值从而从list的Adpater中获得对应的Cursor对象。

通过Cursor构造Alarm对象。

更新闹钟状态 Alarms.enableAlarm(this,alarm.id,!alarm.enabled)

如果闹钟之前是停用状态,那么弹出一个Toast,告诉用户闹钟什么时候会响。

情况3:用户选择了编辑些闹钟

构造出闹钟对应的Alarm对象。

然后启动闹钟设置界面,并将此Alarm作为Intent的额外参数传递。

到这里,文章也够长了,,对于这个类有了一个基本的认识一些普通的代码分析到这里。

其它方法的分析还是另外写一篇吧。

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. Android抓包方法(一)之Fiddler代理
  3. Android(安卓)消息机制(Handler Looper Message )理解
  4. Android动态加载JAR包的实现方法
  5. JavaScript与Android原生相互调用并传参
  6. Android中MotionEvent的来源和ViewRootImpl
  7. 使用ActionBar,调整Theme时遇到You need to use a Theme.AppCompa
  8. [Android] 40个比较重要的Android面试题,必知
  9. Android中3种全屏方法及3种去掉标题栏的方法

随机推荐

  1. Android linux adc驱动(s5pv210)
  2. android webview在弹出软键盘时,布局没有
  3. [置顶] Android基于XMPP Smack Openfire
  4. android之ListView与Adapter(结合JavaBea
  5. Android五大布局详解——LinearLayout(线
  6. Android DatePickerDialog存在执行两次on
  7. android 利用Canvas显示局部图片
  8. android解析xml的通用写法
  9. android 通知栏处理
  10. Android上HDMI介绍(基于高通平台)