<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/setting" android:orderInCategory="50" android:showAsAction="always" android:title="setting"/> <item android:id="@+id/action_share" android:icon="@drawable/share" android:orderInCategory="65" android:showAsAction="ifRoom" android:title="share"/> <item android:id="@+id/action_search" android:icon="@drawable/search_lense" android:orderInCategory="70" android:showAsAction="ifRoom|collapseActionView" android:title="search"/> </menu>
android:showAsAction="ifRoom"ifRomm表示有空间的时候显示。
android:showAsAction="always"表示总是显示
android:showAsAction="never"表示总是不显示
android:showAsAction="ifRoom|withText"有空间的时候同时显示title标题
android:showAsAction="fRoom|collapseActionView"有空间的时候折叠title标题
package com.abc.action; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class CActionBarActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return super.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { // TODO 自动生成的方法存根 switch (item.getItemId()) { case R.id.action_search: Toast.makeText(this, "The search selected", Toast.LENGTH_SHORT).show(); break; case R.id.setting: Toast.makeText(this, "The setting selected", Toast.LENGTH_SHORT).show(); break; case R.id.action_share: Toast.makeText(this, "The share selected", Toast.LENGTH_SHORT).show(); break; } return super.onOptionsItemSelected(item); } }
getMenuInflater().inflate(R.menu.menu, menu);等价于
MenuInflater inflater=getMenuInflater(); inflater.inflate(R.menu.menu, menu);onCreateOptionsMenu()方法用来获取menu文件夹中定义的menu.xml文件,用来显示action bar。
效果图:
从上图我们可以 看出明明有三个ActionButton,但是却只显示出两个,接下来就通过overflow来显示多个
(2)带有三个点的overflow菜单栏
只需要在onCreateOptionsMenu(Menu menu) 方法中调用getoverflowMenu这个方法即可
由于手机硬件情况的不同,在有物理Menu键的手机上,ActionBar的overflow按钮会有显示不出
来的情况,可以通过反射的方式修改ViewConfiguration类中的sHasPermanentMenuKey静态变量的
值永远为false,系统就是根据这个变量值来判断手机有没有物理Menu键
private void getOverflowMenu() { //此方法是高手破解后强制overflow显示的一段代码 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(); } }
这是在真机上的效果图
这是在虚拟机上
解决办法还是有有的
按一下自带的menu键,隐藏的action button 就会从下面弹出
1、获取ActionBar对象
2、设置action bar 的 navigation mode
3、添加 action bar的 tabs
4、为每个tabs设置监听事件
5、将Tab加入ActionBar中
import java.lang.reflect.Field; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; 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.view.ViewConfiguration; import android.widget.Toast; public class CActionBarActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); /* getActionBar().setBackgroundDrawable(this.getBaseContext().getResources().getDrawable(R.drawable.BackBar)); getActionBar().show();*/ //1、 ActionBar ActionBar actionbar = getActionBar(); //2、 设置action bar 的 navigation mode actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //3、 添加 action bar的 tabs Tab等价于ActionBar.Tab Tab SnowTab = actionbar.newTab().setText("Snow_Fragment").setIcon(R.drawable.snow_org); Tab SunTab = actionbar.newTab().setText("Sun_Fragment").setIcon(R.drawable.sunny_org); //图片与文字可根据需要进行判断是否添加 // 将Activity的头部标题(图片的右侧)去掉/添加 actionbar.setDisplayShowTitleEnabled(true); //给左上角图标的左边加上一个返回的图标 actionbar.setDisplayHomeAsUpEnabled(true); //使左上角返回的图标见可点击,并进行显示与否操作 actionbar.setDisplayShowHomeEnabled(true); /*(1) * MyTabsListener SunTab = new MyTabsListener(new SunFragment()); SnowTab.setTabListener(SunTab); MyTabsListener SnowTab = new MyTabsListener(new SnowFragment()); SunTab.setTabListener(SnowTab); (2) // 实例化 fragment action bar 是用 fragment 来显示的 Fragment sunFragment = new SunFragment(); Fragment snowFragment = new SnowFragment(); SnowTab.setTabListener(new MyTabsListener(sunFragment)); SunTab.setTabListener(new MyTabsListener(snowFragment));*/ // 4、为每个tabs设置监听事件 //(3) SunTab.setTabListener(new MyTabsListener(new SunFragment())); SnowTab.setTabListener(new MyTabsListener(new SnowFragment())); //5、 将Tab加入ActionBar中 actionbar.addTab(SnowTab); actionbar.addTab(SunTab); } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); getOverflowMenu(); return super.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; case R.id.action_search: Toast.makeText(this, "The search selected", Toast.LENGTH_SHORT).show(); break; case R.id.setting: Toast.makeText(this, "The setting selected", Toast.LENGTH_SHORT).show(); break; case R.id.action_share: Toast.makeText(this, "The share selected", Toast.LENGTH_SHORT).show(); break; } return super.onOptionsItemSelected(item); } private void getOverflowMenu() { //此方法是高手破解后强制overflow显示的一段代码 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(); } } // 实例化 tabs 的监听类 class MyTabsListener implements ActionBar.TabListener { private Fragment fragment; // 接收每个Tab对应的Fragment //实现ActionBar.TabListener接口,构造函数中把fragment传进来了,为了更好的控制fragment public MyTabsListener(Fragment fragment) { this.fragment = fragment; } // 重复两次以上点击 tab @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // ft 用来控制 fragment } // 就点击一次 @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.replace(android.R.id.content, fragment); } // 不点击 @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(fragment); } } }
SnowFragment.java
package com.abc.action; import android.app.Fragment; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import android.view.ViewGroup; import android.widget.FrameLayout.LayoutParams; public class SnowFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.snow_fragment, container, false); return view; } }
SunFragment.java
package com.abc.action; import android.app.Fragment; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout.LayoutParams; import android.widget.LinearLayout; import android.widget.TextView; public class SunFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //在Fragment中调用getActivity()方法获取Activity的实例 TextView textView = new TextView(getActivity()); //获取到Activity实例后,在Fragment中就可以通过该实例调用Activity中的方法了。另外,当Fragment需要Context对象时,也可以使用该方法 //获取Tabs中的文本 textView.setText("SUN"); //此过程可以在布局文件中完成,可参考SnowFragment.java textView.setGravity(Gravity.CENTER_HORIZONTAL); LinearLayout layout = new LinearLayout(getActivity()); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); layout.addView(textView, params); return layout; } }
snow_fragment.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="SNOW"/> </LinearLayout>sun_fragment.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" /> </LinearLayout>
效果图:
actionbar.newTab().setText("Snow_Fragment").setIcon(R.drawable.snow_org);
// 将Activity的头部标题(图片的右侧)去掉/添加
actionbar.setDisplayShowTitleEnabled(true);
//给左上角图标的左边加上一个返回的图标
actionbar.setDisplayHomeAsUpEnabled(true);
//使左上角返回的图标见可点击,并进行显示与否操作
actionbar.setDisplayShowHomeEnabled(true);
使返回小图标可以起到返回主菜单的功能 只需要在onOptionsItemSelected中添加相应的case即可
4、也可以将ActionBar放在手机底部,只需要在配置清单文件AndroidManifest.xml的Activity中添加android:uiOptions="splitActionBarWhenNarrow"即可public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true;
<item
android:id="@+id/action_search"
android:icon="@drawable/search_lense"
android:orderInCategory="60"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView"
android:title="search"/>
上图为折叠和展开的搜索视窗的操作栏
<resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> </style> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item><!--Tabs的背景颜色 --> </style> </resources>
在AndroidManifest.xml文件中可以引用样式主题,区别:
可以在<Activity>中为一个Activity定义一个主题,也可以在中<Application>中为整个应用程序定义一个主题,如下所示:
<application android:theme="@style/CustomActionBarTheme" 或者 <activity android:theme="@style/CustomActionBarTheme"
效果图:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item> </style> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <!-- android:theme="@style/CustomActionBarTheme" --> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item> <!-- Tabs的背景颜色 --> </style> <style name="MyActionBarTabText" parent="@android:style/Widget.Holo.ActionBar.TabText" > <!-- android:allowBackup="true" --> <item name="android:textColor">#ff9900</item><!-- Tabs的字体颜色 --> </style> </resources>
当自定义Tabs字体的时候可在清单文件中的application中添上这样一句代码
是否允许备份用户基础数据
android:allowBackup="true"
(5)自定义Tab Indicator
为了可以明确分辨出我们当前选中的是哪一个Tab项,通常情况下都会在选中Tab的下面加上一条横线作为标识,这被称作Tab Indicator。那么上图中的Tab Indicator就是蓝色的,那么我们接下来就学习一下如何自定义Tab Indicator。首先我们需要重写actionBarTabStyle这个属性,然后将它指向一个新建的Tab样式,然后重写background这个属性即可。需要注意的是,background必须要指定一个state-list drawable文件,这样在各种不同状态下才能显示出不同的效果
由(4)(5)的Tabs可以观察出我做的这两个截图的颜色相比(5)的颜色稍浅一点(为了便于理解Tab Indicator),这是因为在自定义Tab Indicator的时候每个按钮都是有两张图片组成的,也就是说我在这用了4张图片,只需要在style.xml中加入自己的图片
actionbar_tab_indicatorxml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > 引入四张已存在图片 <item android:drawable="@drawable/tab_unselected" android:state_pressed="false" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected" android:state_pressed="false" android:state_selected="true"/> <item android:drawable="@drawable/tab_unselected_pressed" android:state_pressed="true" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_pressed" android:state_pressed="true" android:state_selected="true"/> </selector>
style.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <!-- 这是item的背景修改,不按时透明,按时显示绿色 --> <!-- 4 --> <item name="android:selectableItemBackground">@drawable/up_background</item> <!-- 1 --> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> <!-- 2 --> <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item> <!-- 3 --> <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item> </style> <!-- 1 --> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <!-- android:theme="@style/CustomActionBarTheme" --> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item><!-- Tabs的背景颜色 --> </style> <!--2 --> <style name="MyActionBarTabText" parent="@android:style/Widget.Holo.ActionBar.TabText" > <!-- android:allowBackup="true" --> <item name="android:textColor">#ff9900</item><!-- Tabs的字体颜色 --> </style> <!-- 3 --> <style name="MyActionBarTabs" parent="@android:style/Widget.Holo.ActionBar.TabView"> <!--自定义图片 --> <item name="android:background">@drawable/actionbar_tab_indicator</item> </style> </resources>
对比注释<!-- 1 --><!-- 2 --><!-- 3 -->
在注释
<!-- 4 --> 中引用自定义的图片 <item name="android:selectableItemBackground">@drawable/up_background</item>
下面是自定义的两张图片编码和效果图:
up_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:drawable="@drawable/press_background" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
press_background.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="#ff0000" /> <!--红色 --> </shape>
<resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> </style> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item><!--Tabs的背景颜色 --> </style> </resources>
在AndroidManifest.xml文件中可以引用样式主题,区别:
可以在<Activity>中为一个Activity定义一个主题,也可以在中<Application>中为整个应用程序定义一个主题,如下所示:
<application android:theme="@style/CustomActionBarTheme" 或者 <activity android:theme="@style/CustomActionBarTheme"
效果图:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item> </style> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <!-- android:theme="@style/CustomActionBarTheme" --> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item> <!-- Tabs的背景颜色 --> </style> <style name="MyActionBarTabText" parent="@android:style/Widget.Holo.ActionBar.TabText" > <!-- android:allowBackup="true" --> <item name="android:textColor">#ff9900</item><!-- Tabs的字体颜色 --> </style> </resources>
当自定义Tabs字体的时候可在清单文件中的application中添上这样一句代码
是否允许备份用户基础数据
android:allowBackup="true"
(5)自定义Tab Indicator
为了可以明确分辨出我们当前选中的是哪一个Tab项,通常情况下都会在选中Tab的下面加上一条横线作为标识,这被称作Tab Indicator。那么上图中的Tab Indicator就是蓝色的,那么我们接下来就学习一下如何自定义Tab Indicator。首先我们需要重写actionBarTabStyle这个属性,然后将它指向一个新建的Tab样式,然后重写background这个属性即可。需要注意的是,background必须要指定一个state-list drawable文件,这样在各种不同状态下才能显示出不同的效果
由(4)(5)的Tabs可以观察出我做的这两个截图的颜色相比(5)的颜色稍浅一点(为了便于理解Tab Indicator),这是因为在自定义Tab Indicator的时候每个按钮都是有两张图片组成的,也就是说我在这用了4张图片,只需要在style.xml中加入自己的图片
actionbar_tab_indicatorxml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > 引入四张已存在图片 <item android:drawable="@drawable/tab_unselected" android:state_pressed="false" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected" android:state_pressed="false" android:state_selected="true"/> <item android:drawable="@drawable/tab_unselected_pressed" android:state_pressed="true" android:state_selected="false"/> <item android:drawable="@drawable/tab_selected_pressed" android:state_pressed="true" android:state_selected="true"/> </selector>
style.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="CustomActionBarTheme" parent="@android:style/Theme.Holo"> <!-- 这是item的背景修改,不按时透明,按时显示绿色 --> <!-- 4 --> <item name="android:selectableItemBackground">@drawable/up_background</item> <!-- 1 --> <item name="android:actionBarStyle">@style/MyCustomActionBar</item> <!-- 2 --> <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item> <!-- 3 --> <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item> </style> <!-- 1 --> <style name="MyCustomActionBar" parent="@android:style/Widget.Holo.ActionBar"> <!-- android:theme="@style/CustomActionBarTheme" --> <item name="android:background">#00cc00</item><!-- ActionBar的背景颜色 --> <item name="android:backgroundStacked">#006600</item><!-- Tabs的背景颜色 --> </style> <!--2 --> <style name="MyActionBarTabText" parent="@android:style/Widget.Holo.ActionBar.TabText" > <!-- android:allowBackup="true" --> <item name="android:textColor">#ff9900</item><!-- Tabs的字体颜色 --> </style> <!-- 3 --> <style name="MyActionBarTabs" parent="@android:style/Widget.Holo.ActionBar.TabView"> <!--自定义图片 --> <item name="android:background">@drawable/actionbar_tab_indicator</item> </style> </resources>
对比注释<!-- 1 --><!-- 2 --><!-- 3 -->
在注释
<!-- 4 --> 中引用自定义的图片 <item name="android:selectableItemBackground">@drawable/up_background</item>
下面是自定义的两张图片编码和效果图:
up_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:drawable="@drawable/press_background" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
press_background.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="#ff0000" /> <!--红色 --> </shape>
下篇文章我将会继续介绍未完成的ActionBar (二)
项目资源下载