之前我一直用ActionBarSherlock這個開源項目來做ActionBar,因為它可以讓低版本的設備也能用上ActionBar。但是在最新的SDK中Google提供了一個AppCompat的工程作為libary。它里面就提供了向低版本兼容的ActionBar,所以我們就直接用官方的庫就行了。這里需要注意的是,如果你是用最新的Eclipse with SDK自動創建的工程,那么就沒有問題,如果是自己建立的工程,那么就需要設置style文件和添加一些命名空間,具體步驟請參照:http://blog.csdn.net/xyz_lmn/article/details/12623609。所以這里還是推薦大家去升級最新的SDK和ADT,我是用Eclipse來編寫的。其他的編譯器,如android studio,可能有不同的方式。
新版本中的一些注意事項請參照官方文檔中的說明(懶得翻牆,這是國內轉載過來的):
http://www.tuicool.com/articles/ZnmqYr
一、一些常規的設置
actionBar = getSupportActionBar();//初始化ActionBar actionBar.setDisplayHomeAsUpEnabled(true);//顯示左邊的小箭頭 actionBar.setDisplayShowHomeEnabled(true);//顯示home圖片 setTitle("標題");//設置標題 actionBar.setIcon(getResources().getDrawable(R.drawable.ic_launcher));//設置左邊的圖標 actionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.bar_color));//設置背景圖
如果想在xml文件中設置左邊的小圖標,或者是title文字,那么給activity定義如下屬性即可
<activity android:name="com.example.actionbartest.MainActivity" android:label="天氣" android:logo="@drawable/weather" > </activity>
label就是title,logo就是ico
顯示和隱藏
case R.id.hide_button_id: actionBar.hide(); break; case R.id.show_button_id: actionBar.show(); break;
二、給ActionBar中添加MenuItem
1)從xml文件中靜態添加
在res/menu下建立一個xml文件,我這里叫做main,添加如下代碼:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="com.kale.actionbar.MainActivity" > <item android:id="@+id/action_settings" android:showAsAction="withText" android:title="菜單" app:showAsAction="always"> <!-- android:icon="@drawable/ic_launcher" --> <!-- 如果菜單下面有group,建議菜單項是永遠顯示的。如果用never,就會出現二級菜單的別扭操作 --> <menu> <!-- 定義菜單類型checkableBehavior:single(單選菜單)/all(多選)/none(普通) --> <group android:checkableBehavior="none" > <item android:id="@+id/menu01_id" android:icon="@drawable/ic_launcher" android:title="選項01"/> <item android:id="@+id/menu02_id" android:title="選項02"/> </group> </menu> </item> <!-- 一個最簡單的菜單 --> <item android:icon="@drawable/ic_refresh" android:showAsAction="withText" android:title="simple" app:showAsAction="always"/> <!-- 自定義的視圖菜單 --> <item android:id="@+id/clock_item_id" android:showAsAction="withText" android:title="clock" app:actionLayout="@layout/clock" app:showAsAction="always"/> </menu>
* 官方推薦每一個item項都要有icon和title圖標,因為系統默認顯示的是圖標,
* 而且當屏幕空間不夠的時候,未顯示的菜單就會隱藏到列表中,而列表中只能顯示title字段的值。
<item android:id="@+id/clock_item_id" android:showAsAction="withText" android:title="clock" app:actionLayout="@layout/clock" app:showAsAction="always"/>
這里需要特別注意的是,文件要有自己的命名空間。而且設置showAsAction或actionLayout時需要用自定義命名空間中的屬性,否則無效!
然后我們在代碼中使用回調函數和相應的監聽器就能得到按鈕的事件了
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); AnalogClock clock = (AnalogClock) MenuItemCompat.getActionView(menu.findItem(R.id.clock_item_id)); if (clock == null) { System.out.println("------------------->null"); } else { System.out.println("-------------not null -----------"); } if (FLAG == 1) { createMenu(menu); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.home: break; case R.id.homeAsUp: break; default: break; } Toast.makeText(getApplicationContext(), item.getTitle(), 0).show(); return super.onOptionsItemSelected(item);
2)用代碼添加菜單
除了用xml文件添加菜單外,我們還可以在代碼中對菜單進行添加:
private void createMenu(Menu menu) { // add (int groupId, int itemId, int order, int titleRes) MenuItem item01 = menu.add(0, 01, 0, "No 1"); MenuItemCompat.setShowAsAction(item01, MenuItemCompat.SHOW_AS_ACTION_NEVER); MenuItem item02 = menu.add(0, 02, 0, "No 2"); MenuItemCompat.setShowAsAction(item02, MenuItemCompat.SHOW_AS_ACTION_NEVER); }
然后在方法中初始化即可
@Override public boolean onCreateOptionsMenu(Menu menu) { createMenu(menu); return true; }
三、添加ActionMode菜單
Android 3.0以前,我們處理列表的長按事件經常使用Context Menu,Android3.0以后,我們有了新的選擇:ActionMode。下圖左邊效果為Context Menu右邊效果為ActionMode。
但對於長按出現菜單這個事件,我還是推薦用Context Menu來做,因為現在手機屏幕越來越大,點擊上方或者下方都是很別扭的事情,中間的彈出菜單式比較好的選擇。
圖片來自:http://xyzlmn.blog.51cto.com/2532390/1344872
使用ActionMode需要3步:
1、實現ActionMode.Callback接口
2、處理ActionMode的生命周期
3、調用startSupportActionMode(Callback callback)方法
1、建立類,繼承接口。2、在里面處理初始化的內容和點擊事件
/** * @author:Jack Tony * @tips :處理ActionMode的生命周期事件 * 感謝:http://xyzlmn.blog.51cto.com/2532390/1344872 * @date :2014-7-27 */ private class ActCallback implements ActionMode.Callback { /* * @see * android.support.v7.view.ActionMode.Callback#onCreateActionMode(android * .support.v7.view.ActionMode, android.view.Menu) 第一次初始化的時候調用 */ @Override public boolean onCreateActionMode(ActionMode arg0, Menu menu) { MenuItem saveItem = menu.add("save").setIcon(R.drawable.ic_compose); MenuItemCompat.setShowAsAction(saveItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem searchItem = menu.add("Search").setIcon(R.drawable.ic_search); MenuItemCompat.setShowAsAction(searchItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem refreshItem = menu.add("Refresh").setIcon(R.drawable.ic_refresh); MenuItemCompat.setShowAsAction(refreshItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); return true; } /* * @see * android.support.v7.view.ActionMode.Callback#onPrepareActionMode(android * .support.v7.view.ActionMode, android.view.Menu) 在初始化后和每次重新構建的時候調用 */ @Override public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) { return false; } /* * @see * android.support.v7.view.ActionMode.Callback#onActionItemClicked(android * .support.v7.view.ActionMode, android.view.MenuItem) 但控件被點擊的時候調用 */ @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { Toast.makeText(MainActivity.this, "Got click: " + item.getTitle(), Toast.LENGTH_SHORT).show(); mode.finish(); return false; } /* * @see * android.support.v7.view.ActionMode.Callback#onDestroyActionMode(android * .support.v7.view.ActionMode) 當mode被關閉的時候調用 */ @Override public void onDestroyActionMode(ActionMode arg0) { } }
3、在按鈕上調用方法 (補充:ActionMode mMode;)
case R.id.openMode_button_id: mMode = startSupportActionMode(new ActCallback()); mMode.setTitle("Mode Title"); break; case R.id.closeMode_button_id: if (mMode != null) { mMode.finish(); } break;
完整Java代碼:
package com.kale.actionbar; import android.os.Bundle; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.support.v7.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AnalogClock; import android.widget.Toast; public class MainActivity extends ActionBarActivity { ActionBar actionBar; ActionMode mMode; static int FLAG = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); actionBar = getSupportActionBar();//初始化ActionBar actionBar.setDisplayHomeAsUpEnabled(true);//顯示左邊的小箭頭 actionBar.setDisplayShowHomeEnabled(true);//顯示home圖片 setTitle("標題");//設置標題 actionBar.setIcon(getResources().getDrawable(R.drawable.ic_launcher));//設置左邊的圖標 actionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.bar_color));//設置背景圖 } private void createMenu(Menu menu) { // add (int groupId, int itemId, int order, int titleRes) MenuItem item01 = menu.add(0, 01, 0, "No 1"); MenuItemCompat.setShowAsAction(item01, MenuItemCompat.SHOW_AS_ACTION_NEVER); MenuItem item02 = menu.add(0, 02, 0, "No 2"); MenuItemCompat.setShowAsAction(item02, MenuItemCompat.SHOW_AS_ACTION_NEVER); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); AnalogClock clock = (AnalogClock) MenuItemCompat.getActionView(menu.findItem(R.id.clock_item_id)); if (clock == null) { System.out.println("------------------->null"); } else { System.out.println("-------------not null -----------"); } if (FLAG == 1) { createMenu(menu); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.home: break; case R.id.homeAsUp: break; default: break; } Toast.makeText(getApplicationContext(), item.getTitle(), 0).show(); return super.onOptionsItemSelected(item); } public void buttonListener(View v) { switch (v.getId()) { case R.id.hide_button_id: actionBar.hide(); break; case R.id.show_button_id: actionBar.show(); break; case R.id.addItem_button_id: FLAG = 1; supportInvalidateOptionsMenu(); break; case R.id.deleteItem_button_id: FLAG = 0; supportInvalidateOptionsMenu(); break; case R.id.openMode_button_id: if (mMode == null) { mMode = startSupportActionMode(new ActCallback()); mMode.setTitle("Mode Title"); } break; case R.id.closeMode_button_id: if (mMode != null) { mMode.finish(); mMode = null; } break; default: break; } } /** * @author:Jack Tony * @tips :處理ActionMode的生命周期事件 * 感謝:http://xyzlmn.blog.51cto.com/2532390/1344872 * @date :2014-7-27 */ private class ActCallback implements ActionMode.Callback { /* * @see * android.support.v7.view.ActionMode.Callback#onCreateActionMode(android * .support.v7.view.ActionMode, android.view.Menu) 第一次初始化的時候調用 */ @Override public boolean onCreateActionMode(ActionMode arg0, Menu menu) { MenuItem saveItem = menu.add("save").setIcon(R.drawable.ic_compose); MenuItemCompat.setShowAsAction(saveItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem searchItem = menu.add("Search").setIcon(R.drawable.ic_search); MenuItemCompat.setShowAsAction(searchItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem refreshItem = menu.add("Refresh").setIcon(R.drawable.ic_refresh); MenuItemCompat.setShowAsAction(refreshItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); return true; } /* * @see * android.support.v7.view.ActionMode.Callback#onPrepareActionMode(android * .support.v7.view.ActionMode, android.view.Menu) 在初始化后和每次重新構建的時候調用 */ @Override public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) { return false; } /* * @see * android.support.v7.view.ActionMode.Callback#onActionItemClicked(android * .support.v7.view.ActionMode, android.view.MenuItem) 但控件被點擊的時候調用 */ @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { Toast.makeText(MainActivity.this, "Got click: " + item.getTitle(), Toast.LENGTH_SHORT).show(); mode.finish(); return false; } /* * @see * android.support.v7.view.ActionMode.Callback#onDestroyActionMode(android * .support.v7.view.ActionMode) 當mode被關閉的時候調用 */ @Override public void onDestroyActionMode(ActionMode arg0) { } } }