今天我看Google Training上对于设置Action Bar的内容,扫除了一小块Android盲区,简单记录。
由于教程上没有Sample可以下载,自己又没经验,但又想实践一下,本渣废了一天的劲,踩了不少坑,根据教程上的代码自己时间了一下,截图如下:
下面,就教程和自己实践时的坑,按顺序记录:
虽然国内的APP除了微信,对APP Bar的使用频率不是很高,但是Google一直很推崇,把它作为Activity最重要的设计要素之一,它能让许多APP保持一致性,让用户快速上手,除此之外,他也有很多优点。
- 让用户一眼看出来自己在哪个APP
- 可以让用户预知一些view的功能,比如看到放大镜就知道是搜索
- 支持导航和view切换
ToolBar作为v7 appcompat类库里的一个APP Bar组件,它有很多Action Bar不具备的有点,比如能适配更多设备,随着APP的开发,也能让你随心所欲的去定制。
这次有四个内容:
- 建立一个APP Bar
- 添加和处理Action
- 添加向上返回Action
- Action View和Action Provider
一:建立一个APP Bar
一个起始的APP Bar包含应用的名字,和一个浮动菜单,如下所示:
虽然样式简单,却展现给用户最有用的信息和对APP的一致性的体验。
我们为什么不用ActionBar,确实在每个版本的Android中都会默认把它作为App bar,不过它的样式随着Android版本的不同而不同,而ToolBar能够兼容所有版本的设备,而且它的样式是官方的最新样式。
除了能适配更多的设备,ToolBar相比于ActionBar能在更低版本的设备上引入material design,一种很高大上的设计,我也不懂。有这么多优势,当然要优先使用它了。
加入App Bar分为下面几步:
- 加入v7 appcompat支持库
- Activity继承AppCompatActivity
在Manifest文件里用包含appcompat’sNoActionBar的样式之一指定Activity的样式,防止原生的ActionBar作为 APP Bar
< application android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
在布局文件里加入ToolBar
<android.support.v7.widget.Toolbar
android:id="@+id/my_toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:elevation="4dp"
app:titleTextColor="@android:color/white"
/>
- 在onCreate()方法里调用setSupportActionBar()
如果我们要使用ActionBar的各种方法,只需要先调用getSupportActionBar(),取得示例,然后就可以任性调用了。
2.添加和处理Action
我们可以在APP Bar上添加和处理Action,比如添加一个Action:
我们应该把最重要,最常用的方法添加在上面,如果空间不够了,多余的Action就会被移到浮动菜单那里,就是三个点那里。
添加Action
添加Action很简单,只要在menu的资源文件里面定义< item >,就行了:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- "Mark Favorite", should appear as action button if possible -->
<item
android:id="@+id/action_favorite"
android:icon="@drawable/ic_favorite_black_48dp"
android:title="@string/action_favorite"
app:showAsAction="ifRoom"/>
<!-- Settings, should always be in the overflow -->
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
app:showAsAction="never"/>
</menu>
app:showAsAction ,我们指定这个属性来说明Action到底显示在那里,如果是 ifRoom,意思是如果APP Bar还有足够的空间,我就显示,不够我就放进浮动菜单里,如果是 never,就是说我就放在浮动菜单里。
对Action添加响应
当用户选中了APP Bar的其中一个内容的时候,系统会自动回调onOptionsItemSelected()方法,系统会将被选中的MenuItem传递过去。我们通过检查MenuItem的ID的方法来判断哪个Menu被选中,然后执行不同的操作,如果都不是,我们应该回调超类的方法来处理,下面是示例:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
// User chose the "Settings" item, show the app settings UI...
return true;
case R.id.action_favorite:
// User chose the "Favorite" action, mark the current item
// as a favorite...
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
3.添加向上返回Action
人性化设计的APP应该让用户知道如何返回APP主页面,这时给在APP Bar添加向上返回按钮可以做到这一点,它会导航回APP的主页面。
声明一个ParentActivity
为了让一个Activity能有这样的功能,我们应该指定这个Activity的父Activity的什么。我们可以在app的manifest文件里声明 android:parentActivityName这个属性。
这个属性是在Android4.1版本引入,为了支持更低版本的设备,我们应该在< meta-data >定义一个name-value对,name是“android.support.PARENT_ACTIVITY”,value自然就是这个Activity的名字了。
下面是官方的示例:
<application ... >
...
<!-- The main/home activity (it has no parent activity) -->
<activity
android:name="com.example.myfirstapp.MainActivity" ...>
...
</activity>
<!-- A child of the main activity -->
<activity
android:name="com.example.myfirstapp.MyChildActivity"
android:label="@string/title_activity_child"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
</application>
让返回Action生效
这个很简单,我们只要调用setDisplayHomeAsUpEnable()方法即可,通常来讲,我们应该在onCreate()方法里调用,下面是官方示例:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_child);
// my_child_toolbar is defined in the layout file
Toolbar myChildToolbar =
(Toolbar) findViewById(R.id.my_child_toolbar);
setSupportActionBar(myChildToolbar);
// Get a support ActionBar corresponding to this toolbar
ActionBar ab = getSupportActionBar();
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
}
我们不需要再onOptionsItemSelected()方法里去捕捉这一事件然后处理,估计也没多少人能想到这一部分,我们应该把它交给这个方法的超类自己处理就好。
4.Action Views 和 Action Providers
他们是两个多种多样的组件:
Action View里面内置了APP Bar许多有用的功能呢个,比如搜索内容,点击search action后,用户可以搜索内容,然不会影响activity或是fragment的布局
Action Provider给用户提供了自己定义布局样式的机会。别看它和别的Action外观差不多,但是用户点击之后的行为你都可以定义,比如再弹出来一个菜单
一般用的最多的就是SearchView对输入进行搜索,以及ShareActionProvider来和其他APP分享数据。
添加Action View
添加Action View和添加Action Button差别不大,但是你还要添加下面两个属性的其中一个:
- actionViewClass:执行这个action组件的类
- actionLayout:action对应的布局资源
将showAsAction 属性设置成”ifRoom|collapseActionView”或者是 “never|collapseActionView”,collapseActionView属性的意思是,在不交互的时候,它就是APP Bar上的一个Icon或是Menu里面的item,但当用户选中它之后,他就会填满整个APP Bar。
官方给出了一个定义action view的示例:
<item android:id="@+id/action_search"
android:title="@string/action_search"
android:icon="@drawable/ic_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
选中后的效果变化如图所示:
如果你需要构造一下这个Action View,你应该在onCreateOptionsMenu()方法里先找到对应的MenuItem,然后调用getActionView()来取得ActionView实例,接下来你就可以设置你想要的内容了:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView =
(SearchView) MenuItemCompat.getActionView(searchItem);
// Configure the search info and add any event listeners...
return super.onCreateOptionsMenu(menu);
}
相应Action View的展开
先说明一点,关于点击后它的展开我们不用的onOptionsItemSelected()里面处理,我们只要覆写这方法,然后把它交给这个方法的超类就好了,就像向上返回按钮那样。
如果要在action view展开或是收缩的时候做一些事情,我们应该定义一个类,然后让这个类去继承MenuItemCompat.OnActionExpandListener接口,在调用setOnActionExpandListener()给对应的MenuItem设置监听即可,下面是官方示例:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options, menu);
// ...
// Define the listener
OnActionExpandListener expandListener = new OnActionExpandListener() {
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when action item collapses
return true; // Return true to collapse action view
}
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
return true; // Return true to expand action view
}
};
// Get the MenuItem for the action item
MenuItem actionMenuItem = menu.findItem(R.id.myActionItem);
// Assign the listener to that action item
MenuItemCompat.setOnActionExpandListener(actionMenuItem, expandListener);
// Any other things you have to do when creating the options menu…
return true;
}
添加一个Action Provider
还是和添加普通的Action Button一样,但是要加上actionProviderClass属性,把这个属性设置成所引用组件的完全限定类型。
官方给出了一个定义ShareActionProvider的例子:
<item android:id="@+id/action_share"
android:title="@string/share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
对于这个例子来说定义Icon并不重要,因为ShareActionProvider自带绘图,如果你非要自定义就加上Icon属性就好。
好了,今天就是这么多了。