1.Action Bar 介绍
我们能在应用中看见的actionbar一般就是下图的样子,比如快图应用
1.App icon 应用的图标,左侧带应用相当于back返回键
2.ViewControl
3.Action button 相当于普通的Button可以监听点击事件
4.Action overflow 三个点,相当于手机上的menu键,可以显示隐藏的action button
下面是一个简单的关于Action Bar的例子:
package com.example.demo_actionbarbasic; import com.example.demo_actionbarbasic.R; import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends Activity { private MenuItem menuItem = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 通过hilde()和show()方法可以控制actionbar的隐藏和显示 // ActionBar actionBar = getActionBar(); // actionBar.hide(); // actionBar.show(); } // 我们可以看到,actonbar的用法跟选项菜单是一样的 @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_refresh: Toast.makeText(this, "Menu Item refresh selected", Toast.LENGTH_SHORT).show(); break; case R.id.action_about: Toast.makeText(this, "Menu Item about selected", Toast.LENGTH_SHORT) .show(); break; case R.id.action_edit: Toast.makeText(this, "Menu Item edit selected", Toast.LENGTH_SHORT) .show(); break; case R.id.action_search: Toast.makeText(this, "Menu Item search selected", Toast.LENGTH_SHORT).show(); break; case R.id.action_help: Toast.makeText(this, "Menu Item settings selected", Toast.LENGTH_SHORT).show(); break; default: break; } return super.onOptionsItemSelected(item); } }
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_settings" android:orderInCategory="100" android:showAsAction="never" android:title="settings"/> <item android:id="@+id/action_refresh" android:icon="@drawable/navigation_refresh" android:orderInCategory="101" android:showAsAction="ifRoom|withText" android:title="refresh"/> <item android:id="@+id/action_about" android:icon="@drawable/action_about" android:orderInCategory="101" android:showAsAction="ifRoom" android:title="about"/> <item android:id="@+id/action_search" android:icon="@drawable/action_search" android:orderInCategory="103" android:showAsAction="ifRoom"/> <item android:id="@+id/action_edit" android:icon="@android:drawable/ic_menu_edit" android:orderInCategory="105" android:showAsAction="ifRoom" android:title="edit"/> <item android:id="@+id/action_help" android:showAsAction="always" android:title="help"/> <item android:id="@+id/action_email" android:icon="@android:drawable/ic_dialog_email" android:orderInCategory="106" android:showAsAction="ifRoom" android:title="email"/> </menu>
onCreateOptionsMenu()方法用来加载menu文件夹中定义的xml文件,用来显示action bar。onOptionsItemSelected()方法用来加入点击事件。
效果图:
左图的效果我们看到只能显示两个action button,由于屏幕的空间有限,其他的action button会被隐藏。横屏的时候我们可以显示4个,还有3个被隐藏起来了。当我们按手机上的更多键时可以显示出来关于action button的文字信息,一定要在item标签中加入title属性。
android:showAsAction="ifRoom"ifRomm表示有空间的时候显示。
android:showAsAction="always"表示总是显示
android:showAsAction="ifRoom|withText"有空间的时候同时显示title标题
其他属性可以自己试试。
2.显示3个点的更多action button
从上面的代码我们知道,即使我们横屏也显示不出全部action button。我们可以加入3个点的action button来用下拉显示的方式,显示跟多的action button。在网上的信息得知,只要你的手机有menu键actionbar就不会显示3个点的更多或者说3个点的menu按钮。从上面的代码我们知道,即使我们横屏也显示不出全部action button。我们可以加入3个点的action button来用下拉显示的方式,显示跟多的action button。在网上的信息得知,只要你的手机有menu键actionbar就不会显示3个点的更多或者说3个点的menu按钮。
private void getOverflowMenu() { try { ViewConfiguration config = ViewConfiguration.get(this); Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); if(menuKeyField != null) { menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); } } catch (Exception e) { e.printStackTrace(); } }
代码:Demo_ActionBar3dot
动态action button
用到了MenuItem 类的,setActionView()和collapseActionView()这两个方法。 这个例子的效果是当我们点击refresh action button的时候会显示进度条。
package com.example.demo_actionbar; import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; public class MainActivity extends Activity { private MenuItem menuItem = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case R.id.action_refresh: menuItem = item; menuItem.setActionView(R.layout.progressbar); TestTask task = new TestTask(); task.execute("test"); break; case R.id.action_about: Toast.makeText(this, "Menu Item about selected", Toast.LENGTH_SHORT) .show(); break; default: break; } return super.onOptionsItemSelected(item); } private class TestTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { // Simulate something long running try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { menuItem.collapseActionView(); // 这个方法需要 API 14 以上 menuItem.setActionView(null); } }; }
2.实现ActionBar.OnNavigationListener这个接口,接口中有点击item的事件
3.设置navigation mode例如
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
4.用 setListNavigationCallbacks()方法来实现下拉选项,例如
actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
效果图:
代码:
package in.wptrafficanalyzer.actionbardropdownnavigation; import android.app.ActionBar; import android.app.ActionBar.OnNavigationListener; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.Toast; public class MainActivity extends Activity { /** An array of strings to populate dropdown list */ String[] actions = new String[] { "Bookmark", "Subscribe", "Share" }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); /** Create an array adapter to populate dropdownlist */ ArrayAdapter<String> adapter = new ArrayAdapter<String>( getBaseContext(), android.R.layout.simple_spinner_dropdown_item, actions); /** Enabling dropdown list navigation for the action bar */ getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); /** Defining Navigation listener */ ActionBar.OnNavigationListener navigationListener = new OnNavigationListener() { @Override public boolean onNavigationItemSelected(int itemPosition, long itemId) { Toast.makeText(getBaseContext(), "You selected : " + actions[itemPosition], Toast.LENGTH_SHORT).show(); return false; } }; /** * Setting dropdown items and item navigation listener for the actionbar */ getActionBar().setListNavigationCallbacks(adapter, navigationListener); } }代码下载:Demo_ActionBarDropdownNavigation
Action Bar之Contextual action bar
两张图,前一张是没有显示contextual action bar 的时候,后面那张是用户长点击EditText显示contextual action bar的效果。contextual action bar 也能加入menu item 并对menu item 进行监听。在contextual action bar 中显示 menu item 需要在 /res/menu/ 文件夹中加入布局文件。
代码:
package com.example.demo_actionbarcontextual; import com.example.demo_actionbarcontextual.R; import android.app.Activity; import android.os.Bundle; import android.view.ActionMode; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { protected Object mActionMode; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View view = findViewById(R.id.myView); // 对EditText设置长点击事件,用来显示 contextual action bar view.setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View view) { if (mActionMode != null) { return false; } // Start the Contextual Action Bar using the ActionMode.Callback defined above mActionMode = MainActivity.this .startActionMode(mActionModeCallback); view.setSelected(true); return true; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.mainmenu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "Just a test", Toast.LENGTH_SHORT).show(); return true; } private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { // Called when the action mode is created; startActionMode() was called public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); // R.menu.contextual 是 contextual action bar 的布局文件, 在 /res/menu/ 文件夹下 inflater.inflate(R.menu.contextual, menu); return true; } // Called each time the action mode is shown. Always called after // onCreateActionMode, but // may be called multiple times if the mode is invalidated. public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; // Return false if nothing is done } // 当用户点击 contextual action bar 的 menu item 的时候产生点击事件 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.toast: Toast.makeText(MainActivity.this, "Selected menu", Toast.LENGTH_LONG).show(); mode.finish(); // 关闭 contextual action bar return true; default: return false; } } // Called when the user exits the action mode public void onDestroyActionMode(ActionMode mode) { mActionMode = null; } }; }下载:Demo_ActionBarContextual
Action bar 之 navigation tabs
左图是竖直屏幕的效果,右图是横屏的效果:
代码:
package de.arvidg.exampleactionbartabs; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; public class StartActivity extends Activity { public static Context appContext; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); appContext = getApplicationContext(); // ActionBar ActionBar actionbar = getActionBar(); // 设置action bar 的 navigation mode actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // 添加 action bar 的 tabs ActionBar.Tab PlayerTab = actionbar.newTab().setText("Fragment A"); ActionBar.Tab StationsTab = actionbar.newTab().setText("Fragment B"); // 实例化 fragment action bar 是用 fragment 来显示的 Fragment PlayerFragment = new AFragment(); Fragment StationsFragment = new BFragment(); // 对 tabs 设置监听事件 PlayerTab.setTabListener(new MyTabsListener(PlayerFragment)); StationsTab.setTabListener(new MyTabsListener(StationsFragment)); // 最后把 tabs 加入监听事件 actionbar.addTab(PlayerTab); actionbar.addTab(StationsTab); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuitem_search: Toast.makeText(appContext, "search", Toast.LENGTH_SHORT).show(); return true; case R.id.menuitem_add: Toast.makeText(appContext, "add", Toast.LENGTH_SHORT).show(); return true; case R.id.menuitem_share: Toast.makeText(appContext, "share", Toast.LENGTH_SHORT).show(); return true; case R.id.menuitem_feedback: Toast.makeText(appContext, "feedback", Toast.LENGTH_SHORT).show(); return true; case R.id.menuitem_about: Toast.makeText(appContext, "about", Toast.LENGTH_SHORT).show(); return true; case R.id.menuitem_quit: Toast.makeText(appContext, "quit", Toast.LENGTH_SHORT).show(); return true; } return false; } // @Override // protected void onSaveInstanceState(Bundle outState) { // super.onSaveInstanceState(outState); // outState.putInt("tab", getActionBar().getSelectedNavigationIndex()); // } } // 实例化 tabs 的监听类 class MyTabsListener implements ActionBar.TabListener { public Fragment fragment; // 传入监听的 tab 的 fragment public MyTabsListener(Fragment fragment) { this.fragment = fragment; } // 重复两次以上点击 tab @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // ft 用来控制 fragment Toast.makeText(StartActivity.appContext, "Reselected!", Toast.LENGTH_SHORT).show(); } // 就点击一次 @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.replace(R.id.fragment_container, fragment); } // 不点击 @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(fragment); }
Action bar 之 ShareActionProvider
1.首先要在menu布局文件的item标签中加入
android:actionProviderClass="android.widget.ShareActionProvider"
2.得到ShareActionProvider的实例
provider = (ShareActionProvider) menu.findItem(R.id.menu_share)
.getActionProvider();
3.设置Intent
效果图:
代码:
package com.example.demo_shareactionprovider; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.view.MenuItem; import android.widget.ShareActionProvider; public class MainActivity extends Activity { ShareActionProvider provider = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); // Get the ActionProvider provider = (ShareActionProvider) menu.findItem(R.id.menu_share) .getActionProvider(); // Initialize the share intent Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, "Text I want to share"); provider.setShareIntent(intent); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_share: break; default: break; } return super.onOptionsItemSelected(item); } }
/res/menu/activity_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_share" android:actionProviderClass="android.widget.ShareActionProvider" android:showAsAction="ifRoom" android:title="Share"/> <item android:id="@+id/item1" android:icon="@android:drawable/ic_menu_call" android:showAsAction="ifRoom" android:title=""> </item> </menu>
代码:Demo_ShareActionProvider
Action Bar 之 style
你可以用android的style和theme来自定义action bar的风格和主题
android:windowActionBarOverlay 这个属性是用来定义actionbar和其下方视图的位置关系的。默认false,当设置成true时,表示activity layout 就是说你的下方的视图将覆盖整个屏幕。这样设置的好处就是说,当你隐藏action bar的时候,视图不会改变位置。当我们把action bar设置成半透明的时候,我们也能看见其下面的内容,这样的界面对用户来说更加有好。
<SomeView android:layout_marginTop="?android:attr/actionBarSize" />
上面这个属性可以设置activity layout距离屏幕顶端的距离。这样设置可以防止被action bar覆盖下方内容。
下面是一个简单的关于如何改变antion bar 字体、分割图片、背景的一个style
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- the theme applied to the application or activity --> <style name="CustomActivityTheme" parent="@android:style/Theme.Holo"> <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item> <item name="android:actionBarDivider">@drawable/ab_divider</item> <item name="android:actionBarItemBackground">@drawable/ab_item_background</item> </style> <!-- style for the action bar tab text --> <style name="CustomTabTextStyle" parent="@android:style/TextAppearance.Holo"> <item name="android:textColor">#2456c2</item> </style> </resources>
能设置的关于action bar的风格(style)的属性有:
android:actionButtonStyle // Defines a style resource for the action item buttons.
android:actionBarItemBackground //Defines a drawable resource for each action item's background. (Addedin API level 14.)
android:itemBackground // Defines a drawable resource for each overflow menu item's background.
android:actionBarDivider // Defines a drawable resource for the divider between action items.(Added in API level 14.)
android:actionMenuTextColor //Defines a color for text that appears in an action item.
android:actionMenuTextAppearance //Defines a style resource for text that appears in an action item.
android:actionBarWidgetTheme //Defines a theme resource for widgets that are inflated into the actionbar as action views. (Added in API level 14.)
下面的网址是源码中的styles.xml和themes.xml文件,包含了系统中所有的样式和主题。根据自己的需要可以改变action bar的显示风格。
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/styles.xml
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml
例子1:怎么改变tab的字体大小、字体颜色等
在themes.xml文件中关于tab的属性有:
android:actionBarTabStyle // Defines a style resource for tabs in the action bar.android:actionBarTabBarStyle // Defines a style resource for the thin bar that appears below the navigation tabs.
android:actionBarTabTextStyle //Defines a style resource for text in the navigation tabs.
在themes.xml文件中找到:
<itemname="actionBarTabTextStyle">@style/Widget.Holo.Light.ActionBar.TabText</item>在style.xml文件中找到
<style name="Widget.Holo.Light.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText">在style.xml文件中通过Widget.Holo.ActionBar.TabText,我们可以找到下面
<style name="Widget.Holo.ActionBar.TabText" parent="Widget.ActionBar.TabText"> <item name="android:textAppearance">@style/TextAppearance.Holo.Medium</item> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">12sp</item> <item name="android:textStyle">bold</item> <item name="android:textAllCaps">true</item> <item name="android:ellipsize">marquee</item> <item name="android:maxLines">2</item> </style>
下面是我们工程中styles.xml的内容:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="CustomActivityThemo" parent="@android:style/Theme.Holo.Light"> <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item> </style> <style name="CustomTabTextStyle" parent="@android:style/Widget.ActionBar.TabText"> <item name="android:textSize">25sp</item> <item name="android:textColor">#FF0000</item> <item name="android:textStyle">italic|bold</item> </style> </resources>
我们必须在manifest.xml文件中的activity标签中设置
<activity android:theme="@style/CustomActivityThemo" >
.... </activity>
代码:Demo_ActionBarTabsColor
例子2:改变action bar中tab的indicator(下面的那条横线)的颜色
styles.xml文件内容:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the theme applied to the application or activity --> <style name="CustomActivityTheme" parent="@android:style/Theme.Holo.Light"> <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item> <item name="android:actionBarTabBarStyle">@android:color/holo_orange_dark</item> <item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Example</item> </style> <!-- style for the action bar tab text --> <style name="CustomTabTextStyle" parent="@android:style/TextAppearance.Holo"> <item name="android:textColor">#2456c2</item> </style> <style name="ActionBarTabStyle.Example" parent="@android:style/Widget.Holo.Light.ActionBar.TabView"> <item name="android:background">@drawable/tab_indicator_ab_example</item> </style> </resources>
android:background这个属性定义了tab的显示风格,对应的是一个xml文件不是图片
tab_indicator_ab_example.xml文件的内容:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Non focused states --> <item android:drawable="@android:color/transparent" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_example" android:state_focused="false" android:state_pressed="false" android:state_selected="true"/> <!-- Focused states --> <item android:drawable="@drawable/tab_unselected_focused_example" android:state_focused="true" android:state_pressed="false" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_focused_example" android:state_focused="true" android:state_pressed="false" android:state_selected="true"/> <!-- Pressed --> <!-- Non focused states --> <item android:drawable="@drawable/tab_unselected_pressed_example" android:state_focused="false" android:state_pressed="true" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_pressed_example" android:state_focused="false" android:state_pressed="true" android:state_selected="true"/> <!-- Focused states --> <item android:drawable="@drawable/tab_unselected_pressed_example" android:state_focused="true" android:state_pressed="true" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_pressed_example" android:state_focused="true" android:state_pressed="true" android:state_selected="true"/> </selector>代码:Demo_ActionBarTabsColor参考文献:
http://www.vogella.com/articles/AndroidActionBar/article.htmlhttp://developer.android.com/guide/topics/ui/actionbar.html