繼續完成SDK的NotePad例子,之前說過整個例子的功能大致分為:
1. 便簽(Note)列表的顯示;
2. 便簽內容的編輯與查看,刪除;
3. 便簽標題的編輯;
4. 便簽程式的即時檔案夾(案頭捷徑的建立)
【更新】源碼免費:android SDK 下NotePad例子詳解源碼
我們上篇部落格走到了第二步,下面開始第三步功能的實現
三、便簽標題的編輯
便簽這塊的表結構之前上篇部落格也經看到,note表中有title這個欄位
而我們需要的操作就是,針對某一個note我們能夠編輯其title的功能,:
Title修改之後,在列表中得:
通過上述流程,大致就能看出我們完成模組功能的關鍵點,
1. 需要動態添加功能表項目
實現這個功能,還是要回到,NoteEditor這個類中
public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); Log.i(TAG, "Enter in NoteEditor的onCreateOptionsMenu方法"); // Build the menus that are shown when editing. if (mState == STATE_EDIT) { menu.add(0, REVERT_ID, 0, R.string.menu_revert) .setShortcut('0', 'r') .setIcon(android.R.drawable.ic_menu_revert); if (!mNoteOnly) { menu.add(0, DELETE_ID, 0, R.string.menu_delete) .setShortcut('1', 'd') .setIcon(android.R.drawable.ic_menu_delete); } // Build the menus that are shown when inserting. } else { menu.add(0, DISCARD_ID, 0, R.string.menu_discard) .setShortcut('0', 'd') .setIcon(android.R.drawable.ic_menu_delete); } //【注意】這裡就是我們剛剛添加,使用動態方法出建立功能表項目 if (!mNoteOnly) { Intent intent = new Intent(null, getIntent().getData()); intent.addCategory(Intent.CATEGORY_ALTERNATIVE); menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, new ComponentName(this, NoteEditor.class), null, intent, 0, null); } return true;}
會按照Intent.CATEGORY_ALTERNATIVE到inter-filter裡面找合格activity來完成操作
就會找到TitleEditor這個activity:
<activity android:name="TitleEditor" android:label="@string/title_edit_title" android:theme="@android:style/Theme.Dialog" android:windowSoftInputMode="stateVisible"> <!-- This activity implements an alternative action that can be performed on notes: editing their title. It can be used as a default operation if the user invokes this action, and is available as an alternative action for any note data. --> <intent-filter android:label="@string/resolve_title"> <!-- This is the action we perform. It is a custom action we define for our application, not a generic VIEW or EDIT action since we are not a general note viewer/editor. --> <action android:name="com.android.notepad.action.EDIT_TITLE" /> <!-- DEFAULT: execute if being directly invoked. --> <category android:name="android.intent.category.DEFAULT" /> <!-- ALTERNATIVE: show as an alternative action when the user is working with this type of data. --> <category android:name="android.intent.category.ALTERNATIVE" /> <!-- SELECTED_ALTERNATIVE: show as an alternative action the user can perform when selecting this type of data. --> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> <!-- This is the data type we operate on. --> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter> </activity>
【需要注意】:
注意這裡就會產生一個問題,效果中menuItem的功能表項目如何顯示,即如何找到我們對於string裡的常量的,
經過測試後,發現它會預設先找:
<intent-filter android:label="@string/resolve_title">
這個label標籤,找不到的話,就會往上找, <activity android:name="TitleEditor" android:label="@string/title_edit_title"
就會找到這個activity的label顯示
測試:左圖就是intent-filter有android:label這個屬性時,右圖就是注釋掉intent-filter有android:label這個屬性效果。
2. 完成對彈出title內容的修改
這個應該比較過程應該比較屬性了
/** * 本activity用來編輯便簽標題,顯示一個包含EditText的浮動視窗 */public class TitleEditor extends Activity implements OnClickListener {private static final String TAG = "TitleEditor"; /** * 一個特定的intent Action來標示 編輯便簽標題操作 */ public static final String EDIT_TITLE_ACTION = "com.android.notepad.action.EDIT_TITLE"; /** * 我們需要操作的notes表的兩個欄位,由於後面查詢使用 */ private static final String[] PROJECTION = new String[] { NotePad.Notes._ID, // 0 NotePad.Notes.TITLE, // 1 }; /** title列在note表的的第二列,擷取時列的index為1 */ private static final int COLUMN_INDEX_TITLE = 1; private Cursor mCursor; private EditText mText; private Uri mUri; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "Enter in TitleEditor的onCreate方法"); setContentView(R.layout.title_editor); mUri = getIntent().getData();//擷取我們準備編輯title的note記錄的uri mCursor = managedQuery(mUri, PROJECTION, null, null, null);//擷取該note的cursor //設定該EditText與Button控制項的 事件的監聽 mText = (EditText) this.findViewById(R.id.title); mText.setOnClickListener(this); Button b = (Button) findViewById(R.id.ok); b.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); Log.i(TAG, "Enter in TitleEditor的onResume方法"); // Initialize the text with the title column from the cursor if (mCursor != null) { mCursor.moveToFirst(); mText.setText(mCursor.getString(COLUMN_INDEX_TITLE)); } } @Override protected void onPause() { super.onPause(); Log.i(TAG, "Enter in TitleEditor的onPause方法"); if (mCursor != null) { // Write the title back to the note ContentValues values = new ContentValues(); values.put(Notes.TITLE, mText.getText().toString()); getContentResolver().update(mUri, values, null, null); } } public void onClick(View v) { // 當使用者觸發點擊事件是,就會結束該activity,這時onPause方法就會調用,保持當前的資料 finish(); }}
四、便簽程式的即時檔案夾(案頭捷徑的建立)
這個效果很炫,自己之前剛買智能手機時還不會用呢,後來才發現這個效果非常實用與方便,目的就是在能夠快速讀取我們程式的資料資訊。大家用過肯定知道,長時間按著螢幕就會彈出相應捷徑的設定
:由左至右
分析:要想實現這個效果,我們也要有相應的activity來實現:相應的解釋在源碼中都有,應該很好理解。
public class NotesLiveFolder extends Activity {/** * The URI for the Notes Live Folder content provider. */ public static final Uri CONTENT_URI = Uri.parse("content://" + NotePad.AUTHORITY + "/live_folders/notes"); public static final Uri NOTE_URI = Uri.parse("content://" + NotePad.AUTHORITY + "/notes/#"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Intent intent = getIntent(); final String action = intent.getAction(); //判斷是否建立即時檔案夾 if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) { //設定資料地址 final Intent liveFolderIntent = new Intent(); liveFolderIntent.setData(CONTENT_URI); //設定即時檔案夾的名字,即是捷徑的標題 liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, getString(R.string.live_folder_name)); //設定實施檔案夾的表徵圖 liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON, Intent.ShortcutIconResource.fromContext(this, R.drawable.live_folder_notes)); //設定顯示模式為列表 liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST); //設定單擊之後的事件,這裡是單擊其中一條便簽時 liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT, new Intent(Intent.ACTION_EDIT, NOTE_URI)); // The result of this activity should be a live folder intent. setResult(RESULT_OK, liveFolderIntent); } else { setResult(RESULT_CANCELED); } finish(); }}
同時還有一個比較關鍵的配置是:
<!-- 使用者在案頭上長按後選擇即時檔案夾就會彈出一個可用即時檔案夾的列表對話方塊。若我們想把自己應用程式內的Activity也添加到這一列表中, 同樣只需要在該Activity註冊時添加一個Action為android.intent.action.CREATE_LIVE_FOLDER的IntentFilter。 --> <activity android:name="NotesLiveFolder" android:label="@string/live_folder_name" android:icon="@drawable/live_folder_notes"> <intent-filter> <action android:name="android.intent.action.CREATE_LIVE_FOLDER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
【需要注意】:
1.上面第二個中,在點擊列表表徵圖時才會觸發NotesLiveFolder這個Activity,
列表中該程式是否顯示是由設定檔決定的,可以參考上面配置代碼。
2.
liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, getString(R.string.live_folder_name));
改為:
liveFolderIntent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, "即時的NotePad");
:
到此整個NotePad例子的功能就已經完全實現,呵呵,通過學習真的鞏固了不少之前的知識,加油,繼續努力!