NotePad例子研究

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);

参考:Android 中的 ManagedQuery()

7. 在NoteEditor.onResume方法中

从mCursor中提取出note数据。设定NoteEditor的标题。如果mCursor等于NULL 显示错误信息。

原文地址:https://www.cnblogs.com/fengzhblog/p/2753375.html