先看一下ActionProvider的官方解释:An ActionProvider can be optionally specified for a {@link android.view.MenuItem} and in such a case it will be responsible for creating the action view that appears in the {@link android.app.ActionBar} as a substitute for the menu item when the item is displayed as an action item.
比较绕,需要先搞清楚几个概念,我的理解是这样的
action view: 出现在actionbar里的view都可以成为一个action view, 比如导航图标,title等
我们在写menu的xml文件时会设置showAsAction,当这个属性为always时,这个item就会出现在toolbar中,这种item是action item,也属于action view
当我们设置为never时,出现在溢出框里的item就是menu item,这个就不属于action view了
所以ActionProvider的工作就是负责创建一个action view来代替action item(不是menu item),当然前提是menu文件中已经给该item指定了ActionProvider。
用于当item不固定,需要随着状态改变而变化时,比如硬件连接与断开需要显示不同的图标,或者购物车商品数量
ToolBar和actionbar都可以使用ActionProvider,本文使用ToolBar,实现的效果比较简单,点击按钮,item的title改变。
1 主题设置为NoActionBar
2 在布局文件中加入toolbar,activity中找到控件,并setSupportActionBar(toolbar)(一定要设置);
3 编写menu文件,activity中设置 toolbar.inflateMenu(R.menu.**);
准备ActionProvider
1 自定义类,继承ActionProvider
会提示重写两个方法,第二个方法是你要替换的控件,可以自己写一个布局再inflate,我就用了一个textview
public MyProvider(Context context) {
super(context);
this.context = context;
}
@Override
public View onCreateActionView() {
if (textView == null){
textView = new TextView(context);
}
textView.setOnClickListener(this);
textView.setTextColor(Color.WHITE);
return textView;
}
再加一些数据和背景设置的方法
public void setData(String string){
if (textView != null){
textView.setText(string);
}
}
public void setBackGround(Drawable backGround){
textView.setBackground(backGround);
}
public void setBackGround(int color){
textView.setBackgroundColor(color);
}
@Override
public void onClick(View v) {
Toast.makeText(context,"被点击了",Toast.LENGTH_SHORT).show();
}
2 ActionProvider就完成了,不要忘记在menu文件中给需要的item指定provider,格式是包名+类名
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/one"
android:title="one"
app:showAsAction="always"
app:actionProviderClass="com.myway.actionproviderdemo.MyProvider"/>
<item android:id="@+id/two"
android:title="two"
app:showAsAction="never"
app:actionProviderClass="com.myway.actionproviderdemo.MyProvider"/>
<item android:id="@+id/three"
android:title="three"
app:showAsAction="never"
app:actionProviderClass="com.myway.actionproviderdemo.MyProvider"/>
<item
android:id="@+id/four"
android:title="four"
app:showAsAction="never" />
</menu>
3 接下来就是在activity中使用了
格式都是固定的,重写onCreateOptionsMenu方法,findItem参数是你指定的那个item,通过他得到provider的实例
当然如果要操作多个item,那就findItem多个MenuItem,创建多个provider的实例
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.hello, menu);
MenuItem item = menu.findItem(R.id.one);
actionProvider = (MyProvider) MenuItemCompat.getActionProvider(item);
// MenuItem item1 = menu.findItem(R.id.two);
// actionProvider1 = (MyProvider) MenuItemCompat.getActionProvider(item1);
return true;
}
//点击事件
public void setdata(View view) {
if (actionProvider != null) {
actionProvider.setBackGround(Color.RED);
actionProvider.setData("设置数据");
// actionProvider1.setData("哈哈哈");
}
}
当点击按钮之后就会发现第一个item发生了变化
前面说过了,上述操作对于Action Menu才生效,但是可以看到menu文件中属性是never的item也与provider进行了关联,这就提到provider的另一个作用了
在provider中重写以下方法
@Override
public boolean onPerformDefaultAction() {
Log.i("hahahaha","onPerformDefaultAction 被调用");
return super.onPerformDefaultAction();
}
当用户没有为toolbar设置item的点击事件,但是点击了关联过provider的位于溢出框中的menu item时,系统会调用这个方法,响应点击事件,而没有关联的item是不会响应的;当然如果设置了点击事件,当点击menu item都会响应,点击action menu时只有在provider中设置的点击事件会相应。目前还不知道这个方法有什么实际用途。