ActionBar是在3.0(API 11)新加入的部分,在4.0(API 14)以后成熟化。之前看书学Menu的时候出现了很多问题,而且基本不怎么好解决。(学校图书馆实在都是老书)后来,在网上查资料才发现,ActionBar相当于是将以前的TitleBar和Menu结合起来了。
这里是学习资料,感谢两位老师。
http://blog.csdn.net/guolin_blog/article/details/18234477
http://blog.csdn.net/xyz_lmn/article/details/8132420
接下来,是我自己的学习总结。
第一步、首先我们先创建Actionbar
毕竟我是个菜鸟,我开始用安卓手机的时候都是4.0的时代了。也被低版本的问题困扰了很久,v7包导入了以后出现各种奇怪的问题,而且我也不知道,这里不做讨论。直接设置minSDK=14(4.0),此版本是自带ActionBar的。我们只需要用getActionBar()方法就可以得到ActionBar了。此外,可以通过hide()和show()方法来让ActionBar显示和隐藏(一定要注意布局的变动)
我这边是用一个按钮来操控显示隐藏的
btnActionbar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (flagActionBar) {
actionbar.hide();
btnActionbar.setText("显示ActionBar");
flagActionBar=false;
} else {
actionbar.show();
btnActionbar.setText("隐藏ActionBar");
flagActionBar=true;
}
}
});
跟ActionBar是一个原理,使用getMenuInflater()方法得到填充器,再用inflate()就好
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_actionbar_item, menu);
return true;
}
接着,是在menu文件夹下新建一个Resource.xml文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/item_01"
android:icon="@drawable/fire_theme01"
android:showAsAction="ifRoom|withText"
android:title="@string/actionbar_item_01"/>
<item
android:id="@+id/item_02"
android:icon="@drawable/fire_theme02"
android:showAsAction="ifRoom|withText"
android:title="@string/actionbar_item_02"/>
</menu>
列出了两项,有需求可以再加。这边做个简单说明,icon是图标,title是显示的文字(当然你长按操作项会有Toast显示Title)。showAsAction这个属性呢有
never、always、ifRoom、withText、collapseActionView
前三项对应的呢是选择出现在overflow(三个竖点)外,其中ifRoom是在有足够空间的时候显示在overflow外(推荐使用)。而withText是显示Title在overflow外的(在手机上依旧不显示,平板上显示)。collapseActionView是让该元素能点击后拓展开,并响应事件(以我自己的理解)。
第三步、填充完了,加入菜单的响应点击事件,并简单实现返回的功能(非物理按键型)
首先是
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_01:
Intent intent = new Intent(this, NewActivity01.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
case R.id.item_02:
Intent intent2 = new Intent(this, NewActivity02.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent2);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
这里简单说明一下,一定要return true。这样系统的Menu才不会做处理,交给你响应(我也不懂说的对不对。。。汗)FLAG_ACTIVITY_CLEAR_TOP的作用呢,是当打开新的Activity时,如果以前有了,直接把以前的都关了。(通俗的说就是,Activity1暂停了,打开了Activit2,那么再打开Activity1时,之前的Activity1会自动销毁)这样的好处自然是让系统运行更流畅。
至于向上返回
需要添加
actionBar.setDisplayHomeAsUpEnabled(true);
以及,响应处应为
case android.R.id.home:
finish();
return true;
这样你通过点击最左边的图标,返回父级界面了。
第四步、让overflow里的图标能显示出来
这边其实不太好理解,用的是Java里反射的方法(Java不是太会,只会一点皮毛)我也上网查阅了一些资料,大概就是通过获取方法的名字,然后来改写(大致是这样的吧。。。。汗)
这里用到的是MenuBuilder里的setOptionalIconVisible()方法,默认的是false,我们只要将其改成true就好了。
我这边结合按键来实现的显示与隐藏切换(按钮那部分就不粘了)
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId==Window.FEATURE_ACTION_BAR&&menu!=null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Method method=menu.getClass().getDeclaredMethod("setOptionalIconsVisible",
Boolean.TYPE);
method.setAccessible(true);
method.invoke(menu, flagOverflow);
} catch (Exception e) {
// TODO: handle exception
}
}
}
return super.onMenuOpened(featureId, menu);
}
第五步、添加子菜单
新建一个class,extends ActionProvider
通过onPrepareSubMenu方法来添加子菜单
public void onPrepareSubMenu(SubMenu subMenu) {
subMenu.clear();
subMenu.add("画册").setIcon(R.drawable.fire_theme04)
.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return true;
}
});
subMenu.add("日记").setIcon(R.drawable.fire_theme05)
.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return true;
}
});
}
当然,还要有一个判断方法
@Override
public boolean hasSubMenu() {
return true;
}
这些完成之后,别忘记了,在menu的布局文件里,将你想添加子菜单的菜单项添上(一定要是完整的包名哦~~)
android:actionProviderClass="com.dota.example.myactionbardemo.MyActionBarProvider"
贴士:可以在Manifest里修改application或者activity的属性,logo代表左侧图标,label代表标题
第六步、结合ViewPager+Actionbar.Tab+Fragment来实现可滑动的标签
这里稍稍复杂,我们细细来一、先新建所需的Fragment(片段),这个东西类似Activity,可以看成是数个这玩意组成Activity的。(我又开始按着自己的理解胡说八道了,你们按着自己的理解来)
public class FragmentTree extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tree, container, false);
}
}
以相同的方式完成数个Fragment(记得配好布局xml)
这边有个要注意的地方,因为要涉及ViewPager的使用,这边Fragment的import为
import android.support.v4.app.Fragment;
千万不要弄成
import android.app.Fragment;
不然之后处理会很麻烦
二、导入ViewPager
是在主布局中哦~~~
<android.support.v4.view.ViewPager
android:id="@+id/pagerChange"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
三、添加Tab项
我们通过新建一个类,来将Fragment和Tab联系起来
class MyTab {
private int text;
private Class fragment;
public MyTab(int text, Class fragment) {
this.text = text;
this.fragment = fragment;
}
public int getText() {
return text;
}
public void setText(int text) {
this.text = text;
}
public Class getFragment() {
return fragment;
}
public void setFragment(Class fragment) {
this.fragment = fragment;
}
}
然后新建一个ArrayList,把元素放进去
private List<MyTab> tabs = new ArrayList<MyTab>(3);
tabs.add(new MyTab(R.string.tab_title01, FragmentCookie.class));
tabs.add(new MyTab(R.string.tab_title02, FragmentTree.class));
tabs.add(new MyTab(R.string.tab_title03, FragmentSnowman.class));
这之后,把Tab填进去,并绑定好监听器
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //确立有Tab的导航模式
for (MyTab tab : tabs) {
Tab t = actionbar.newTab();
t.setText(tab.getText()).setTabListener(this);
actionbar.addTab(t);
}
这边TabListener需要implement,并实现3个方法
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
当选中某个Tab时,切换到对应的Pager(其实这个是下一步有关的)
四、实现ViewPager的滑动
viewPager.setAdapter(new TabFragmentPagerAdapter(
getSupportFragmentManager()));
viewPager.setOnPageChangeListener(this);
这边用到了一个Adapter,extends于FragmentPagerAdapter
并且有个要注意的,需将主Activity extends 改成FragmentActivity ,这样才可以用getSupportFragmentManager()方法。除此以外,还要注意接口均是v4的,不是app的。如下:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
让主Activity implement OnPageChangeListener
然后是3个方法
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int i) {
actionbar.selectTab(actionbar.getTabAt(i));
}
最后,把Adapter的部分写下来
class TabFragmentPagerAdapter extends FragmentPagerAdapter {
public TabFragmentPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public Fragment getItem(int i) {
try {
return (Fragment) tabs.get(i).getFragment().newInstance();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
@Override
public int getCount() {
return tabs.size();
}
}
这里,主要是把对应好编号的Tab和Fragment匹配并newInstance一个实例
第七步、自定义样式
这部分我就不详细说了,老师这里写的特别详细,特别好
http://blog.csdn.net/guolin_blog/article/details/25466665
直接上代码吧
<style name="CustomActionBarTheme" parent="android:Theme.Holo.Light">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
<item name="android:actionBarTabStyle">@style/MyActionBarTab</item>
<item name="android:actionBarTabBarStyle">@style/MyActionBarTabBar</item>
<item name="android:actionBarDivider">@drawable/divide01</item>
<item name="android:itemBackground">@drawable/background001</item>
</style>
<style name="MyActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#ffc4ff</item>
<item name="android:titleTextStyle">@style/MyActionBarTitleText</item>
</style>
<style name="MyActionBarTitleText" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<item name="android:textColor">#3a7bbc</item>
</style>
<style name="MyActionBarTabText" parent="@android:style/Widget.Holo.Light.ActionBar.TabText">
<item name="android:textColor">#007fff</item>
<item name="android:textSize">20sp</item>
<item name="android:textStyle">normal</item>
</style>
<style name="MyActionBarTab" parent="@android:style/Widget.Holo.ActionBar.TabView">
<item name="android:background">@drawable/actionbar_tab_indicator</item>
</style>
<style name="MyActionBarTabBar" parent="@android:style/Widget.Holo.ActionBar.TabBar">
<item name="android:background">#000000</item>
</style>
记得编辑完了要在Manifest中引用哦~~
android:theme="@style/CustomActionBarTheme"
我自己又另外加了两个分别用蓝笔,绿笔标出了
蓝笔对应
<item name="android:actionBarDivider">@drawable/divide01</item>
绿笔对应
<item name="android:actionBarTabBarStyle">@style/MyActionBarTabBar</item>
就是颜色配的好像很奇怪,不过还是一点点地又完整地复习了一遍ActionBar的使用。
完整代码下载地址:
http://download.csdn.net/detail/zerolovesc1993/8411991