1. 在AndroidManifest.xml文件中
1.1 NotePadProvider Provider
<provider android:name="NotePadProvider"
android:authorities="com.google.provider.NotePad"
/>
1.2 NotesList Activity
// 添加action.MAIN和category.LAUNCHER
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
// 添加action.VIEW, action.EDIT, action.PICK, category.DEFAULT, data(mimeType)
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
// 添加action.GET_CONTENT, category.DEFAULT, data(mimeType)
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
1.3 NoteEditor Activity
// 设定属性theme, screenOrientation, configChanges
android:theme="@android:style/Theme.Light"
android:screenOrientation="sensor"
android:configChanges="keyboardHidden|orientation"
// 添加action.VIEW, action.EDIT, action.EDIT_NOTE, category.DEFAULT, data(mimeType)
<intent-filter android:label="@string/resolve_edit">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="com.android.notepad.action.EDIT_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
// 添加action.INSERT, category.DEFAULT, data(mimeType)
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
1.4 TitleEditor Activity
// 设定属性theme, windowSoftInputMode
android:theme="@android:style/Theme.Dialog"
android:windowSoftInputMode="stateVisible"
// 添加action.EDIT_TITLE, category.DEFAULT, category.ALTERNATIVE, category.SELECTED_ALTERNATIVE, data(mimeType)
<intent-filter android:label="@string/resolve_title">
<action android:name="com.android.notepad.action.EDIT_TITLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
1.5 NotesLiveFolder Activity
// 添加action.CREATE_LIVE_FOLDER, category.DEFAULT
<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
2. 在NoteList中
// 重写了7个方法
onCreate(Bundle savedInstanceState)
onCreateOptionsMenu(Menu menu)
onPrepareOptionsMenu(Menu menu)
onOptionsItemSelected(MenuItem item)
onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
onContextItemSelected(MenuItem item)
onListItemClick(ListView l, View v, int position, long id)
2.1 在NoteList.onCreate方法中
// to execute a menu shortcut in default key handling.
setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
// 设置Intent data
Intent intent = getIntent();
intent.setData(Notes.CONTENT_URI);
// 设置OnCreateContextMenuListener监听对象
getListView().setOnCreateContextMenuListener(this);
// 在NoteList中实现接口中的抽象方法
onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
// 调用Activity的managedQueue方法获取Cursor
Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null, Notes.DEFAULT_SORT_ORDER);
// 将cursor关联到ListView的Adapter中
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
new String[] { Notes.TITLE }, new int[] { android.R.id.text1 });
setListAdapter(adapter);
2.2 在NoteList中添加Log语句
// 点击“应用图标”打开程序 执行onCreate方法
11-04 13:37:14.743: INFO/NoteList(10303): ++onCreate++
// 首次点击“菜单”按键 先后执行onCreateOptionsMenu、onPrepareOptionsMenu
11-04 13:37:24.832: INFO/NoteList(10303): ++onCreateOptionsMenu++
// 非首次点击“菜单”按键 只执行onPrepareOptionsMenu方法
11-04 13:37:24.832: INFO/NoteList(10303): ++onPrepareOptionsMenu++
// 点击“菜单项” 执行onOptionsItemSelected方法
11-04 13:37:33.261: INFO/NoteList(10303): ++onOptionsItemSelected++
// 点击“列表项” 执行onListItemClick方法
11-04 13:45:46.932: INFO/NoteList(10303): ++onListItemClick++
// 添加3个note之后. 点击最新添加的那个note. position等于0. note的id等于3.
// 长按ListView项. 弹出上下文菜单对话框. 调用onCreateContextMenu方法.
11-04 16:38:53.935: INFO/NoteList(10982): ++onCreateContextMenu++
11-04 16:38:53.935: INFO/NoteList(10982): onCreateContextMenu::position=0
// 在上下文菜单对话框上只有一项. 即delete. 点击delete. 调用onContextItemSelected方法
11-04 16:39:06.157: INFO/NoteList(10982): ++onContextItemSelected++
11-04 16:39:06.157: INFO/NoteList(10982): onContextItemSelected::id=3
2.3 在onCreateContextMenu方法中
// 方法签名onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
// cursor.getString(COLUMN_INDEX_TITLE). 即ListView项的标题
menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
// R.string.menu_delete. 即"Delete"
menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete);
2.4 在onContextItemSelected方法中
// 方法签名onContextItemSelected(MenuItem item)
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
// 点击delete. 调用Provider将数据删除
Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
getContentResolver().delete(noteUri, null, null);
2.5 在onCreateOptionsMenu方法中
// 方法签名onCreateOptionsMenu(Menu menu)
// 添加MenuItem, 设定shortcut, 设定Icon.
menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
.setShortcut('3', 'a')
.setIcon(android.R.drawable.ic_menu_add);
// 怎么理解?
Intent intent = new Intent(null, getIntent().getData());
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
new ComponentName(this, NotesList.class), null, intent, 0, null);
2.6 在onPrepareOptionsMenu方法中
// 方法签名onPrepareOptionsMenu(Menu menu)
// 如果getListAdapter().getCount()大于0
Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());
// 怎么理解?
Intent[] specifics = new Intent[1];
specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
MenuItem[] items = new MenuItem[1];
Intent intent = new Intent(null, uri);
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
items);
items[0].setShortcut('1', 'e');
// 如果getListAdapter().getCount()等于0
menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
2.7 在onOptionsItemSelected方法中
// 方法签名onOptionsItemSelected(MenuItem item)
// 创建Intent方法. Intent(String action, Uri uri)
// Intent.ACTION_INSERT的值是"android.intent.action.INSERT"
startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
// 在AndroidManifest.xml文件中
// NoteEditor Activity的intent-filter元素的action中有"android.intent.action.INSERT"
// 所以在Intent中指定了Intent.ACTION_INSERT就跳转到NoteEditor Activity。
3. 在NoteEditor.LinedEditText中
// LinedEditText继承EditText 是EditText的子类
3.1 在构造方法LinedEditText(Context context, AttributeSet attrs)中
// 创建Rect对象和Paint对象
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0x800000FF);
3.2 在onDraw(Canvas canvas)方法中
// 计算出画横线的位置 画横线
int count = getLineCount();
Rect r = mRect;
Paint paint = mPaint;
for (int i = 0; i < count; i++) {
int baseline = getLineBounds(i, r);
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
}
4. 在NoteEditor.onCreate方法中添加Log语句
11-04 20:09:24.212: INFO/NotePad(16620): ++onCreate++
11-04 20:09:26.995: INFO/NotePad(16620): ++onListItemClick++
11-04 20:09:27.115: INFO/NotePad(16620): onCreate::intent=Intent { act=android.intent.action.EDIT dat=content://com.google.provider.NotePad/notes/1 cmp=com.example.android.notepad/.NoteEditor }
11-04 20:09:27.115: INFO/NotePad(16620): onCreate::action=android.intent.action.EDIT
11-04 20:09:27.115: INFO/NotePad(16620): onCreate::edit::uri=content://com.google.provider.NotePad/notes/1
11-04 20:09:57.074: INFO/NotePad(16620): ++onCreateOptionsMenu++
11-04 20:09:57.094: INFO/NotePad(16620): ++onPrepareOptionsMenu++
11-04 20:09:57.805: INFO/NotePad(16620): ++onOptionsItemSelected++
11-04 20:09:57.935: INFO/NotePad(16620): onCreate::intent=Intent { act=android.intent.action.INSERT dat=content://com.google.provider.NotePad/notes cmp=com.example.android.notepad/.NoteEditor }
11-04 20:09:57.935: INFO/NotePad(16620): onCreate::action=android.intent.action.INSERT
11-04 20:09:57.995: INFO/NotePad(16620): onCreate::insert::uri=content://com.google.provider.NotePad/notes/2
// 如果是action.INSERT时 执行以下语句
setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
action.INSERT在AndroidManifest.xml文件中是NoteEditor的intent-filter的条件之一。
// 设定ContentView 即layout/note_editor.xml文件
5. 在layout/note_editor.xml文件中
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.example.android.notepad.NoteEditor$LinedEditText"
android:id="@+id/note"
// 宽度和高度
android:layout_width="fill_parent"
android:layout_height="fill_parent"
// 其他属性
android:background="@android:color/transparent"
android:padding="5dip"
android:scrollbars="vertical"
android:fadingEdge="vertical"
android:gravity="top"
android:textSize="22sp"
android:capitalize="sentences"
6. 在NoteEditor.onCreate方法中
mCursor = managedQuery(mUri, PROJECTION, null, null, null);
7. 在NoteEditor.onResume方法中
从mCursor中提取出note数据。设定NoteEditor的标题。如果mCursor等于NULL 显示错误信息。