最近在研究网易云音乐的User Interface,首页的Action Bar 还有三个Tab,今天就来研究这个是如何实现的。
我也搜了不少的ActionBar的博客,基本没有什么实例支持,都只是官方文档的翻译。http://blog.csdn.net/xyz_lmn/article/details/8132420
关于ActionBar
首先提下ActionBar,ActionBar是窗体功能来鉴别用户当前在app中的位置,提供给用户一些功能和导航,通过ActionBar可以方便的让系统自动适配不同尺寸的屏幕。
ActionBar包含如下内容:
- App icon
- Action item(项目)
- Action overflow(放不下的item,放在overflow里)
加入一个ActionBar
在你的布局中引入一个ActionBar,只需要2步
- 创建一个活动继承自
ActionBarActivity
(但是现在被AppCompatActivity
替代,所以继承AppCompatActivity
即可) - 在你的activity声明中加入
<activity android:theme="@style/Theme.AppCompat.Light">
删除ActionBar:
可以在程序中运行时隐藏ActionBar,像这样。
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
android系统会自动调整布局来填充,隐藏的ActionBar。如果你希望它显示回来,可以使用show()方法。
首先是右边的两个图标 search和menu 这两个icon 是通过onCreateOptionsMenu()实现的:
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
通过在Menu中设置:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/action_search"
android:icon="@drawable/actionbar_search"
android:showAsAction="ifRoom"
android:title="@string/action_search"/>
<item
android:id="@+id/action_menu"
android:icon="@drawable/actionbar_menu"
android:showAsAction="always"
android:title="@string/action_more"/>
</menu>
showAsAction属性是可以确定item是在overflow里面还是外面。
注意showAsAction这个属性必须要自定义一个名字空间来使用
<span style="white-space:pre"> </span>xmlns:android="http://schemas.android.com/apk/res/android"
<span style="white-space:pre"> </span>xmlns:yourapp="http://schemas.android.com/apk/res-auto"
- ifRoom 会显示在ActionBar 如果屏幕空间不足,则藏到Overflow里
- never 永远只在Overflow里显示,而且只显示标题
- always 总是显示
- withText 尽可能的显示标题。空间不足则不显示
- collapseActionView 声明这个View被折叠到按钮。选择了按钮才会打开。配合ifRoom使用
TypedArray tabIconIds = getResources().obtainTypedArray(R.array.actionbar_icons);
for(int i = 0; i < 3; i++){
View view = getLayoutInflater().inflate(R.layout.actionbar_tab, null);
ImageView tabIcon = (ImageView) view.findViewById(R.id.actionbar_tab_icon);
tabIcon.setImageResource(tabIconIds.getResourceId(i, -1));
actionBar.addTab(actionBar.newTab().setCustomView(view).setTabListener(tabListener));
}
enableEmbeddedTabs(actionBar);
这里使用了TypedArray来自定义属性。即定义tab icon的属性,具体的TypedArray的使用可以学习 http://blog.it985.com/13456.html
actionbar_tab.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/actionbar_tab_icon"
android:layout_width="55dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/actionbar_discover"/>
</LinearLayout>
这里ImageView的src属性的值设置不设置都一样,最后都会从array中的actionbar_icons中顺序读取图片的资源
array中的actionbar_icons.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="actionbar_icons">
<item>@drawable/actionbar_discover</item>
<item>@drawable/actionbar_music</item>
<item>@drawable/actionbar_friends</item>
</string-array>
</resources>
三个item中的值分别是三个icon的选择器这里贴出其中一个的:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/actionbar_discover_selected" android:state_selected="true"/>
<item android:drawable="@drawable/actionbar_discover_normal"/>
</selector>
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
};
如果要将其与Viewpager结合起来,只需添加转换的代码即可(具体的实现方法本人也未测试)。做这些之前别忘记获取ActionBar.....
<span style="white-space:pre"> </span>actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
完成之后,应该就可以看到部分效果了。但是还是有问题,比如我的问题就是只显示一个Tab Icon 另外两个会藏在overflow中,但点开overflow,这三点Tab icon都消失了,但是却占据着三个空间,去网上看别人的代码,他们在style.xml中添加了许多的ActionBar的style,具体是如何什么问题我也不清楚,总之解决了。以下是关于ActionBar的一些style:
<style name="AppTheme" parent="android:Theme.Holo.Light">
<item name="android:actionBarStyle">@style/EmbeddedActionBar</item>
<item name="android:actionBarTabStyle">@style/EmbeddedTabStyle</item>
<item name="android:actionBarTabBarStyle">@style/EmbeddedTabBarStyle</item>
</style>
<style name="EmbeddedActionBar" parent="NormalActionBar"/>
<style name="EmbeddedTabStyle" parent="@android:style/Widget.Holo.Light.ActionBar.TabView">
<item name="android:padding">0dp</item>
<item name="android:gravity">center</item>
<item name="android:background">@drawable/actionbar_tabs_bg</item>
</style>
<style name="EmbeddedTabBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.TabBar">
<item name="android:divider">@null</item>
</style>
<style name="NormalActionBar" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:title">私人FM</item>
<item name="android:titleTextStyle">@style/action_bar_style</item>
<item name="android:background">@color/actionbar_background</item>
</style>
<style name="action_bar_style">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">18sp</item>
</style>
最后的实现效果就是下图: