AcrionBar可以包含基本的按钮以及抽屉图标来展示导航抽屉,我们将要了解怎样使用AppCompatActivity
来支持所有的android版本和一些有力的可扩展的ActionBar特征:
- 使用拆分的action bar 来获得一个顶部个底部的菜单
- 增加ActionView(app:action_layout)和SearchView
组件
- 配置图标的顺序
- 使用ActionProvider
和ShareActionProvider
来获得丰富的作用。
- 配置home图标来向上导航
- 在ActionBar中从碎片中转换菜单图标
让你的活动继承AppCompatActivity来获得良好的兼容性以及改变主题使其更加兼容例如Theme.AppCompat.Light.DarkActionBar
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
-- Customize your theme here. -->
style>
resources>
现在ActionBar已经配置完成,但是我们还要在menu菜单中加入app:showAsAction = "ifRoom"
这可以增加我们对于增加项的支持。
action bar为用户提供了进入当前页面最重要的动作项的权限,像之前一样重写onCreateOptionMenu
加载相应的菜单布局。
使用orderinCategory
来为每一项指定一个整数,越小的整数优先权越高android:orderInCategory = "20"
通过创建自己的ActionBar主题风格来配置风格和相关属性。
-- Define your colors in `res/values/colors.xml` -->
name="simple_yellow">#ECD078
name="primary_blue">#53777A
然后应用主题
...
android:theme="@style/AppTheme" >
我们可以用我们自己的XML文件替换自动的标题。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/app_title"
android:textColor="#ffffff"
android:id="@+id/mytext"
android:textSize="18dp" />
LinearLayout>
然后在代码中 getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);//展示自定义的view
getSupportActionBar().setCustomView(R.layout.actionbar_title);
如果想要在自定义的布局中展示图标的话需要附加一个值getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME)
我们仍然可以重写onCreateOptionMenu
来添加自定义的动作按钮。
如果想要添加一个不只是简单的图标或者是文本的项,例如一个交互功能更加强的控件,一个Actionview可以让你这样做,常见的是SearchView
平时是一个折叠的搜索图标,然后展开显示一个EditText
文本,首先我们需要创建一个布局文件作为ActionView以便以后可以嵌入到ActionBar中。
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
我们可以将此布局文件可以加载到任何一项通过制定app:action_layout
属性
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/miActionButton"
app:showAsAction="ifRoom"
app:actionLayout="@layout/action_view_button"
android:title="Loading..." />
menu>
我们可以通过重写onPrepareOprionsMenu
来获得ActionView的引用
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem actionViewItem = menu.findItem(R.id.miActionButton);
// Retrieve the action-view from menu
View v = MenuItemCompat.getActionView(actionViewItem);
// Find the button within action-view
Button b = (Button) v.findViewById(R.id.btnCustomAction);
// Handle button click here
return super.onPrepareOptionsMenu(menu);
}
首先我们在menu文件中加入SearchView
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" >
<item android:id="@+id/action_search"
android:orderInCategory="5"
android:title="Search"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
menu>
collapseActionView
表明平时将actionview折叠成图标,点击展开
现在我们需要在搜索时添加一个监听器:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// perform query here
// workaround to avoid issues with some emulators and keyboard devices firing twice if a keyboard enter is used
// see https://code.google.com/p/android/issues/detail?id=24599
searchView.clearFocus();
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
自定义图标和文本颜色:
MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
// Use a custom search icon for the SearchView in AppBar
int searchImgId = android.support.v7.appcompat.R.id.search_button;
ImageView v = (ImageView) searchView.findViewById(searchImgId);
v.setImageResource(R.drawable.search_btn);
// Customize searchview text and hint colors
int searchEditId = android.support.v7.appcompat.R.id.search_src_text;
EditText et = (EditText) searchView.findViewById(searchEditId);
et.setTextColor(Color.BLACK);
et.setHintTextColor(Color.BLACK);
}
使用setDisplayHomenAsUpEnabled
方法,Up
相对于返回键是带领用户返回逻辑上的屏幕,这不是基于导航的历史而是屏幕之间的关系,例如在邮件客户端返回键可能会带领用户回到之前的邮件,而up
会一直将用户带回邮件列表。
首先我们指定home用作up
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
我们也可以明确的重写up按钮,通过检查android.R.id.home
id是否被选择
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// This is the up button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
// overridePendingTransition(R.animator.anim_left, R.animator.anim_right);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
这样的话允许我们配置up键按下时的过度效果。
为了指定up
导向的上一个活动,我们可以在AndroidManifest.xml
文件中设置逻辑上的父项。
<activity
android:name="com.example.myfirstapp.ChildActivity"
android:label="@string/title_activity_display_message"
android:parentActivityName="com.example.myfirstapp.ParentActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.ParentActivity" />
activity>
现在每当home图标按下都会导航到父活动,如果你想父活动保持他的状态可以为父活动指定状态为android:launchMode:"SingleTop"
当栈顶活动为父活动时不会在创建新的活动。
如果我们想动态设置up
键而不想在注册文件中的话,我们可以重写getSupportParentActivityIntent()
方法返回想要的基于传入的参数的intent。
public static final String PACKAGE_NAME = "com.myapplication.";
public static final String PARENT_NAME_EXTRA = "ParentClassName";
@Override
public Intent getSupportParentActivityIntent() {
//获得父类的intent
Intent parentIntent = getIntent();
String className = parentIntent.getStringExtra(PARENT_NAME_EXTRA);
// 基于父类名称创造一个意图
Intent newIntent = null;
try {
//使用包名定义类
newIntent = new Intent(this, Class.forName(PACKAGE_NAME + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 随着`up`活动返回intent
return newIntent;
}
然后当我们想要启动新的活动时候,我们需要应用ParentClassNmae
作为父类额外的控制
Intent intent = new Intent(this, ChildActivity.class);
intent.putExtra(ChildActivity.PARENT_NAME|_EXTRA, "PrentActivity");
startActivity(intent);
从碎片中配置actionbar和从活动中非常的相似,但是有点区别。
自动的,android嘉定碎片不想想actionbar提供items,当一个碎片确实想要向actionbar添加项时,需要告知安卓系统,setHasOptionMenu(true)
在onCreate()方法中
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
setHasOptionsMenu(true);
}
现在安卓会调用onCreateOptionsMenu(..)
和相关的方法
要记住任何由碎片添加的items将会衣服在任何现存的items上,包括了由所包含的活动添加的项,你可以使用orderInCategory
来控制顺序。
与活动中相似,在碎片中安卓提供了一个MenuInflater:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.my_menu, menu);
}
处理点击事件也和活动中相同,不同之处在于碎片的onOptionItemSelected(...)
方法只在活动中的此方法不处理点击事件时才会被调用
@Override
public boolean onOptionItemSelected(MenuItem item) {
//处理选项
switch (item.getItemId()) {
case R.id.my_item:
//处理点击
return true;
default:
return super.onOptionItemSelected(item);
}
}
。。