Android-ActionBar扩展

一、关于ActionBar的item:
     1)动态修改item的title和icon:
    有时候ActionBar上的Item需要根据某种状态来显示不同title和icon,比如一些收音机上ActionBar上有控制其是否外放的Item,就要根据收音机是否处于外放状态来显示不同的状态的titel和icon,甚至控制Item是显示还是被折叠。这个就要重写函数onPrepareOptionsMenu()来实现。eg:    
@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.findItem(R.id.action_settings)
            .setIcon(R.drawable.ic_launcher)
            .setTitle("复制")
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
        return super.onPrepareOptionsMenu(menu);
    }
     2)让overflow中的item显示图标:
    通常看到的效果:overflow中的item只显示titel,并没有显示icon。为什么会这样?因为在源码中控制这个显示的变量默认为false。可以查看源码中MenuBuilder.java中的mOptionalIconsVisible。  默认mOptionalIconsVisible = false,而对mOptionalIconsVisible做处理的函数仅有:     
void setOptionalIconsVisible(boolean visible){
        mOptionalIconsVisible = visible;
 }
    居然有函数去设置mOptionalIconsVisible的值,为什么mOptionalIconsVisible的值始终是false。没错,猜的没错,函数setOptionalIconsVisible()没有地方调用,搜索整个Android工程源码,这个函数只处在MenuBuilder类中被定义,没被其他地方调用过,所以mOptionalIconsVisible依旧是默认值false,而我们也不能通过MenuBuilder类来调用这个函数。要将mOptionalIconsVisible的值变为true,就要通过JAVA的反射机制了。在onCreateOptionsMenu()方法中最前面调用下面方法:
 private void setOptionalIconVisible(Menu menu)  
   {  
       try  
       {  
           Class<?> classname= Class.forName("com.android.internal.view.menu.MenuBuilder");  
           Method m = classname.getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);  
           m.setAccessible(true);  
           m.invoke(menu, true);  
             
       } catch (Exception e)  
       {  
           e.printStackTrace();  
       }  
   }  
 如果调用这个方法以后还无效,就要看使用的activity是否用的ActionBarActivity,因为ActionBarActivity是support.v7里面的,MenuBuilder类的路径不同。具体代码如下:
 private void setOptionalIconVisible(Menu menu)  
    {  
        try  
        {  
            Class<?> classname = Class.forName("android.support.v7.internal.view.menu.MenuBuilder");  
            Method m = classname.getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);  
            m.setAccessible(true);  
            m.invoke(menu, true);  
             
        } catch (Exception e)  
        {  
         Log.i(TAG, "not found!");
            e.printStackTrace();  
        }  
    }  

看上面的图显示,终于Overflow里的action 的Icon  和 title同时显示了。然而要实现这种效果还有没有方法呢?还可以通过自定义Action 来实现:     
@Override
 public boolean onCreateOptionsMenu(Menu menu) {
   SubMenu subMenu = menu.addSubMenu("");
       
         subMenu.add("搜索").setIcon(R.drawable.ic_launcher)
             .setOnMenuItemClickListener(new OnMenuItemClickListener() {
               
                 @Override
                 public boolean onMenuItemClick(MenuItem item) {
                     return false;
                 }
             });
       
         subMenu.add("设置").setIcon(R.drawable.ic_launcher)
             .setOnMenuItemClickListener(new OnMenuItemClickListener() {
               
                 @Override
                 public boolean onMenuItemClick(MenuItem item) {
                     return false;
                 }
             });
       
         MenuItem item = subMenu.getItem();
         item.setIcon(R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha);
         item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
  return super.onCreateOptionsMenu(menu);
 }

二、关于ActionBar上的分享Action:
    在<Android-ActionBar>中已经提到过了ActionBar增加 分享provider,这里自定义一个分享provider。
    写一个类继承于ShareActionProvider,并重写部分方法,主要的工作要把分享中原有的subMenu先clear掉,然后重新增加新的submenu,如:
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.ShareActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
public class CustomShareActionProvider extends ShareActionProvider{
    public CustomShareActionProvider(Context context) {
        super(context);
    }
    @Override
    public View onCreateActionView() {
        return null;
    }
    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        //最好先clear submenu,以防内存泄露什么的。
        subMenu.clear();
        subMenu.add("复制").setIcon(R.drawable.abc_ic_menu_copy_mtrl_am_alpha)
               .setOnMenuItemClickListener(new OnMenuItemClickListener() {
               
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    return false;
                }
            });
       
        subMenu.add(R.string.action_settings).setIcon(R.drawable.abc_ic_menu_cut_mtrl_alpha)
            .setOnMenuItemClickListener(new OnMenuItemClickListener() {
               
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    return false;
                }
            });
    }
   
    @Override
    public void setShareIntent(Intent arg0) {
        super.setShareIntent(arg0);
    }
   
}
自定义share provider以后,需要在对应的menu中适配分享item的actionProviderClass属性:
<item
        android:id="@+id/action_share"
        android:icon="@android:drawable/ic_menu_share"
        android:title="分享"
        app:showAsAction="ifRoom"
        app:actionProviderClass="com.example.ActionBar.CustomShareActionProvider"/>

三、简要介绍下使用Split action bar:
    如果你的activity运行在一个屏幕比较小的设备上,Split action bar 在屏幕的底部提供了一个独立的bar,用来显示所有的action Item。
    
    要完成使用Split action bar 需要以下两步:
    1)在清单文件中配置activity或者application的属性:
    2)这项属性要求API-LEVEL最小为14,要支持比较旧的版本,需要配置<meta-data />属性:    
 <manifest ...>
        <activityuiOptions="splitActionBarWhenNarrow" ... >
           <meta-dataandroid:name="android.support.UI_OPTIONS"
                      android:value="splitActionBarWhenNarrow"/>
        </activity>
     </manifest>
四、增加导航Tab:

要达到上面图中的效果,要做以下几步:
   1)实现ActionBar.Tablistener接口(Android官方文档中提到这个已经过时,推荐考虑使用:http://developer.android.com/design/patterns/navigation.html): 
 public class CustomTabListener<T extends Fragment> implements TabListener{
	private Fragment mFragment;
	private final ActionBarActivity mActivity;
	private final String mTag;
        private final Class<T> mClass;
 
	public CustomTabListener(ActionBarActivity activity, String tag, Class<T> clz) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
       }
	@Override
	public void onTabReselected(Tab tab, FragmentTransaction ft) {
             // User selected the already selected tab. Usually do nothing.
	}
	//Tab被选择时调用
	@Override
	public void onTabSelected(Tab tab, FragmentTransaction ft) {
		// 检查Fragment是否已经被初始化
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }	
      }
	//当前Tab 没有被选择时调用。
	@Override
	public void onTabUnselected(Tab tab, FragmentTransaction ft) {
		if (mFragment != null) {
                    // Detach the fragment, because another one is being attached
                    ft.detach(mFragment);
             }
	}
    }
  2)有几个Tab,对应就要几个Fragment:   
public class ArtistFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.artist_fragment, container, false);
        return view;
    }
  }
 public class AlbumFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view =inflater.inflate(R.layout.album_fragment, container, false);
        return view;
    }
  }  
3)给对应的activity中增加Tab:        
protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView(R.layout.activity_msg);
		ActionBar actionBar = getSupportActionBar();
		actionBar.setDefaultDisplayHomeAsUpEnabled(true);
              // Notice that setContentView() is not used, because we use the root
             // android.R.id.content as the container for each fragment
             // setup action bar for tabs
	     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
	    Tab tab = actionBar.newTab().setText(R.string.artist_tab_name)
	    		.setTabListener(new CustomTabListener<ArtistFragment>(this, "artist", ArtistFragment.class));
	    actionBar.addTab(tab);
    
	    tab = actionBar.newTab().setText(R.string.album_tab_name)
	    		.setTabListener(new CustomTabListener<AlbumFragment>(this, "album", AlbumFragment.class));
	    actionBar.addTab(tab);
	}
   需要注意的是:activity的onCreate方法中不需要setContentView() 来加载要显示UI,因为加了Tab以后,要显示的UI来自于两个已建立的Fragment.
五、自定义ActionBar的style:
actionBarStyle:为actionbar 指定各种样式和属性。
actionbar默认style:widget.ActionBar或者Widget.Appcompat.ActionBar(使用了Appcompat.support.v7 library).支持的style包括:
        background:为actionbar定义一张背景图,如果非support.v7,可以是颜色值。例如:<item name="android:background">#008B8B</item>
        backgroundStacked:为actionbar Tabs指定背景。
        backgroundSplit:为Split action bar指定背景。
        actionButtonStyle:为action button指定样式资源,parent style可以指定为:widget.ActionButton或者,Widget.AppCompat.ActionButton.
        actionOverflowButtonStyle:为overflow action items 指定样式资源。parent style可以指定为:Widget.ActionButton.Overflow或者Widget.AppCompat.ActionButton.Overflow.
        displayOptions:指定一个或多个action bar显示选项,比如,是否显示程序的Logo,显示程序的title,又或者 action bar 的 up button 等。
        divider:为action item之间的分割指定资源。
        titleTextStyle:为actionbar的title指定样式资源。
action items style:
        actionButtonStyle:为action button指定样式资源,parent style可以指定为:widget.ActionButton或者,Widget.AppCompat.ActionButton.
        actionBarItemBackground:为action bar items背景指定资源,这资源也可能是state-list drawable,以显示不同的选择状态。
        itemBackground:为每个action bar overflow item的背景指定资源,这资源也可能是state-list drawable,以显示不同的选择状态。
        actionBarDivider:为action items 之间分割指定资源。
        actionMenuTextColor:为每个action item上显示的文本指定颜色资源。
        actionMenuTextAppearance:为每个action item上显示的文本指定样式资源。
        actionBarWidgetTheme:为填充到action bar中的Widgets指定theme资源,如action views。
Navigation tabs style:
        actionBarTabStyle:为action bar中的tab指定资源,parent style可以指定为:Widget.AppCompat.ActionBar.TabView或者Widget.ActionBar.TabView。
        actionBarTabBarStyle:为navigation tabs之间的thin bar指定样式资源。
        actionBarTabTextStyle:为navigation tabs上显示的文本指定样式资源。
样例: 
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat.Light">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/TabTextStyle</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
        <item name="actionBarTabTextStyle">@style/TabTextStyle</item>
        <item name="actionMenuTextColor">@color/actionbar_text</item>
    </style>

    <!-- general styles for the action bar -->
    <style name="MyActionBar"
           parent="@style/Widget.AppCompat.ActionBar">
        <item name="android:titleTextStyle">@style/TitleTextStyle</item>
        <item name="android:background">@drawable/actionbar_background</item>
        <item name="android:backgroundStacked">@drawable/actionbar_background</item>
        <item name="android:backgroundSplit">@drawable/actionbar_background</item>

        <!-- Support library compatibility -->
        <item name="titleTextStyle">@style/TitleTextStyle</item>
        <item name="background">@drawable/actionbar_background</item>
        <item name="backgroundStacked">@drawable/actionbar_background</item>
        <item name="backgroundSplit">@drawable/actionbar_background</item>
    </style>

    <!-- action bar title text -->
    <style name="TitleTextStyle"
           parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>

    <!-- action bar tab text -->
    <style name="TabTextStyle"
           parent="@style/Widget.AppCompat.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>
</resources>
上面的例子,来自于Android官方文档,例子包括了常用情况使用,还一种就是使用support library(eg:support.v7)。
自定义actionbar的背景:
 <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:actionBarStyle">@style/CustomActionBar</item>
    </style>
	
    <style name="CustomActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
        <!-- the action bar background,don't include tab background -->
        <item name="android:background">#008B8B</item>
    </style>

自定义actionbar和tab的背景:    
<style name="AppTheme" parent="AppBaseTheme">
        <item name="android:actionBarStyle">@style/CustomActionBar</item>
    </style>
	
    <style name="CustomActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
        <!-- the action bar background,don't include tab background -->
        <item name="android:background">#008B8B</item>
        <!-- the tab background -->
        <item name="android:backgroundStacked">#00868B</item>
    </style>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值