android ActionBar與Menu - 1 - api demos 學習
android ActionBar與Menu - 2 - email中ActionBar分析
?
這里以Email為例,簡單分析一下ActionBar在實際中的應用
上面是在模擬器上登錄原生Email的截圖
?
這里說一下所謂的原生:
原生不是指大家買來手機之后沒有修改過任何內容,軟件本身的樣子。也不是指google的各種親兒子本身的樣子,因為無論是前者還是后者,最起碼都是要經(jīng)過優(yōu)化和修復bug的,不是親兒子那就很有可能進行了整容,讓你看不出原來的樣子
這里的原生是用google發(fā)布的源碼編譯出來的apk,安裝到手機或模擬器上面大家就可以看到
?
我們主要看看Email如何使用ActionBar和menu的
頁面可以發(fā)現(xiàn),Email既有AcionBar又有menu,menu被放在了底部,先看ActionBar
Email的主Activity是EmailActivity,我就不畫類圖了,因為總是畫不明白,怕誤導大家,所以就用類似堆棧log的形式來介紹
@Override protected void onCreate(Bundle savedInstanceState) { …… initUIController(); …… } private void initUIController() { mUIController = UiUtilities.useTwoPane(this) ? new UIControllerTwoPane(this) : new UIControllerOnePane(this); }
這里初始化了一個UIController,其中的關系是這樣的
UIControllerBase為父類,是一個抽象類,下面有兩個實現(xiàn)類分別為UIControllerOnePane和UIControllerTwoPane(實在理解不了為什么這么命名。。。)
UIControllerOnePane為手機UI實現(xiàn),UIControllerTwoPane為平板UI實現(xiàn),我們這里只考慮UIControllerOnePane
public UIControllerBase(EmailActivity activity) { mActivity = activity; mFragmentManager = activity.getFragmentManager(); mRefreshManager = RefreshManager.getInstance(mActivity); mActionBarController = createActionBarController(activity); if (DEBUG_FRAGMENTS) { FragmentManager.enableDebugLogging(true); } }
這里包含了一個ActionBarController,createActionBarController是抽象方法,下面是UIControllerOnePane的實現(xiàn)
@Override protected ActionBarController createActionBarController(Activity activity) { // For now, we just reuse the same action bar controller used for 2-pane. // We may change it later. return new ActionBarController(activity, activity.getLoaderManager(), activity.getActionBar(), new ActionBarControllerCallback()); }
最關鍵的就是ActionBarController了,它包含ActionBar所有內容
public ActionBarController(Context context, LoaderManager loaderManager, ActionBar actionBar, Callback callback) { mContext = context; mLoaderManager = loaderManager; mActionBar = actionBar; mCallback = callback; mDelayedOperations = new DelayedOperations(Utility.getMainThreadHandler()); mAllFoldersLabel = mContext.getResources().getString( R.string.action_bar_mailbox_list_title); mAccountsSelectorAdapter = new AccountSelectorAdapter(mContext); // Configure action bar. mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_CUSTOM); // Prepare the custom view mActionBar.setCustomView(R.layout.action_bar_custom_view); mActionBarCustomView = (ViewGroup) mActionBar.getCustomView(); // Account spinner mAccountSpinnerContainer = UiUtilities.getView(mActionBarCustomView, R.id.account_spinner_container); mAccountSpinner = UiUtilities.getView(mActionBarCustomView, R.id.account_spinner); mAccountSpinnerDefaultBackground = mAccountSpinner.getBackground(); mAccountSpinnerLine1View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_1); mAccountSpinnerLine2View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_2); mAccountSpinnerCountView = UiUtilities.getView(mActionBarCustomView, R.id.spinner_count); // Account dropdown mAccountDropdown = new AccountDropdownPopup(mContext); mAccountDropdown.setAdapter(mAccountsSelectorAdapter); mAccountSpinner.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mAccountsSelectorAdapter.getCount() > 0) { mAccountDropdown.show(); } } }); }
?從上面可以看出,ActionBar實際上也不復雜,只是設置了顯示選項和一個CustomView,復雜的內容幾乎全部集中在這個CustomView上了
// Configure action bar. mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_CUSTOM); // Prepare the custom view mActionBar.setCustomView(R.layout.action_bar_custom_view); mActionBarCustomView = (ViewGroup) mActionBar.getCustomView();
當點擊CustomView時候會有彈出下拉框,mAccountDropdown就發(fā)揮作用了
private class AccountDropdownPopup extends ListPopupWindow
設置了mAccountSpinner.setOnClickListener,調用到mAccountDropdownshow()
mAccountDropdownshow顯示由mAccountsSelectorAdapter提供
public class AccountSelectorAdapter extends CursorAdapter
其中的數(shù)據(jù)由CursorWithExtras com.android.email.activity.ActionBarController.mCursor提供
mCursor只在一個地方進行刷新,那就是加載賬戶郵箱信息的時候
/** * Load account/mailbox info, and account/recent mailbox list. */ private void loadAccountMailboxInfo(final long accountId, final long mailboxId) { mLoaderManager.restartLoader(LOADER_ID_ACCOUNT_LIST, null, new LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return AccountSelectorAdapter.createLoader(mContext, accountId, mailboxId); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mCursor = (AccountSelectorAdapter.CursorWithExtras) data; updateTitle(); } @Override public void onLoaderReset(Loader<Cursor> loader) { mCursor = null; updateTitle(); } }); }
我們可以發(fā)現(xiàn),加載完畢之后Cursor更新了,然后updateTitle,不用去看函數(shù)也能猜出這里是更新ActionBar
為了刷新列表,調用了下面語句
mAccountsSelectorAdapter.swapCursor(mCursor);
updateTitle就不再進行分析了,里面幾乎都是刷新那個CustomView的內容
?
下面看看底部的菜單,之前的學習中,api demos里并沒有演示這種情況,我們用hierarchyviewer查看,發(fā)現(xiàn)頁面上下都是一個ActionBarContainer的容器
上面的ActionBar我們已經(jīng)知道它是怎么來的了,那下面的呢?原因在于manifest的配置
?
<activity android:name=".activity.EmailActivity" android:uiOptions="splitActionBarWhenNarrow" > </activity>
splitActionBarWhenNarrow使得ActionBar被拆分成上下兩個部分
splitActionBarWhenNarrow 用于顯示Activity在窄屏設備(如豎屏手機)上運行時的所有menu項。當然,如果手機有menu鍵的時候,當menu項過多而顯示不下的時候按Menu鍵即可
這時迷題已解,沒有什么神秘的地方了,看看menu配置,一目了然
?
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/compose" android:orderInCategory="100" android:alphabeticShortcut="c" android:title="@string/compose_action" android:icon="@drawable/ic_menu_compose_normal_holo_light" android:showAsAction="ifRoom" /> <item android:id="@+id/search" android:orderInCategory="200" android:alphabeticShortcut="s" android:title="@string/search_action" android:icon="@drawable/ic_menu_search_holo_light" android:showAsAction="ifRoom" /> <item android:id="@+id/show_all_mailboxes" android:orderInCategory="300" android:alphabeticShortcut="c" android:title="@string/mailbox_list_account_selector_show_all_folders" android:icon="@drawable/ic_menu_move_to_holo_light" android:showAsAction="ifRoom" /> <item android:id="@+id/refresh" android:orderInCategory="400" android:alphabeticShortcut="r" android:title="@string/refresh_action" android:icon="@drawable/ic_menu_refresh_holo_light" android:showAsAction="ifRoom" /> <!-- Note the order; we want to show them to the right of delete/move --> <item android:id="@+id/newer" android:orderInCategory="1500" android:icon="@drawable/menu_item_newer" android:showAsAction="always" android:visible="false" /> <item android:id="@+id/older" android:orderInCategory="1600" android:icon="@drawable/menu_item_older" android:showAsAction="always" android:visible="false" /> <item android:id="@+id/mailbox_settings" android:orderInCategory="2000" android:title="@string/mailbox_settings_action" android:icon="@android:drawable/ic_menu_preferences" /> <item android:id="@+id/account_settings" android:orderInCategory="3000" android:title="@string/settings_action" android:icon="@android:drawable/ic_menu_preferences" /> </menu>
當我們橫屏的時候,menu就會跑到上面去了
?
?
下面是帶回退導航的
他能使用戶回到上一個頁面(并不是上一個activity,回到上一個activity可以通過按back鍵實現(xiàn))
?
mActionBar.setDisplayOptions(showUp ? ActionBar.DISPLAY_HOME_AS_UP : 0, ActionBar.DISPLAY_HOME_AS_UP);
在之前的refreshInernal中已經(jīng)設置過了
?
當我們打開或新建一個郵件的時候,頁面會跳轉到新的activity
public class MessageCompose extends Activity implements OnClickListener, OnFocusChangeListener, DeleteMessageConfirmationDialog.Callback, InsertQuickResponseDialog.Callback
這里我們看到了,頁面依然有回退導航,點擊之后能回退到上一個頁面,當然,不再是當前的activity了
那么它是如何做到的,代碼如下
?
@Override public boolean onOptionsItemSelected(MenuItem item) { if (handleCommand(item.getItemId())) { return true; } return super.onOptionsItemSelected(item); } private boolean handleCommand(int viewId) { switch (viewId) { case android.R.id.home: onBack(false /* systemKey */); return true; …… } /** * Handle a tap to the system back key, or the "app up" button in the action bar. * @param systemKey whether or not the system key was pressed */ private void onBack(boolean systemKey) { finish(); if (isOpenedFromWithinApp()) { // If opened from within the app, we just close it. return; } if (isOpenedFromWidget() || !systemKey) { // Otherwise, need to open the main screen for the appropriate account. // Note that mAccount should always be set by the time the action bar is set up. startActivity(Welcome.createOpenAccountInboxIntent(this, mAccount.mId)); } }
點擊回退導航時,觸發(fā)的menu是android.R.id.home?
剩下的事情就好辦了,這里交給了onBack來處理
?
?
至此Email應用的ActionBar和menu就基本分析完了,如果有不準確的地方還希望大家指正
?
?
最后附上別人的幾篇翻譯,內容很基礎,也比api demos多,值得一看
Android 用戶界面---操作欄(Action Bar 一) :基本操作
Android 用戶界面---操作欄(Action Bar 二) :分離式ActionBar與回退導航
Android 用戶界面---操作欄(Action Bar 三) :ActionView
Android 用戶界面---操作欄(Action Bar 四) :ActionProvider與Tab
Android 用戶界面---操作欄(Action Bar 五) :主要是關于樣式
?
?
轉貼請保留以下鏈接
本人blog地址
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
