toolbar之menu高级用法

前言

在通用的menu使用中,通常的使用方式有以下两类:

 

图片形式菜单和文字形式菜单,但是这两种形式并不能满足所有需求,在实际项目中也可能需要同时需要使用图片和文字,

如同下图:

本文将以两种形式介绍图片+文字实现菜单

  1. 自定义ActionProvider
  2. 通过ActionLayout定义菜单布局

先看效果:

  • 自定义ActionProvider

首先自定义CustomActionProvider继承ActionProvider,因为Toolbarsupport包下的,所以我们要用support下的ActionProvider类,这个类是在support.v4下,它是兼容ToolbarActionBar;

public class CustomActionProvider extends ActionProvider {
    public CustomActionProvider(Context context) {
        super(context);
    }

    @Override
    public View onCreateActionView() {
        return view;
    }

}

这里需要定义一个显示的view

<?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="match_parent"
    android:background="?actionBarItemBackground"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/filter" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textColor="@android:color/white" />
</LinearLayout>

特别说明一下,android:background="?actionBarItemBackground" 是引用系统默认Toolbar/ActionBarMenu的点击效果,

然后完善我们的CustomActionProvider,

public class CustomActionProvider extends ActionProvider {

    public CustomActionProvider(Context context) {
        super(context);
    }

    TextView mTitle;
    ImageView mIcon;

    @Override
    public View onCreateActionView() {
        //读取support下Toolbar/ActionBar的高度,为了让这个Menu高和宽和系统的menu达到一致
        int size = getContext().getResources().getDimensionPixelSize(
                android.support.design.R.dimen.abc_action_bar_default_height_material);

        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(size, size);
        View view = LayoutInflater.from(getContext())
                .inflate(R.layout.layout_menu_provider, null, false);
        view.setLayoutParams(layoutParams);
        mTitle = view.findViewById(R.id.tv_title);
        mIcon = view.findViewById(R.id.iv_image);
        view.setOnClickListener(mOnClickListener);
        return view;
    }

    View.OnClickListener mOnClickListener;

    public void setOnClickListener(View.OnClickListener onClickListener) {
        this.mOnClickListener = onClickListener;
    }
}

添加自定义方法,供外部调用:

public void setIcon(@DrawableRes int resId) {
    mIcon.setImageResource(resId);
}

public void setText(@StringRes int resId) {
    mTitle.setText(resId);
}

public void setText(CharSequence text) {
    mTitle.setText(text);
}

到这里,准备工作完成,然后是如何使用:  
<?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/menu1"
        android:title="@string/menutext1"
        app:actionProviderClass="com.banzhi.toolbardemo.CustomActionProvider"
        app:showAsAction="always" />

</menu>

这里需要说明的是我们引用的app:actionProviderClass="com.banzhi.toolbardemo.CustomActionProvider"是以app开头,而不是android.然后是java代码:

    CustomActionProvider actionProvider;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_custom, menu);
        final MenuItem menuItem = menu.findItem(R.id.menu1);
        actionProvider = (CustomActionProvider) MenuItemCompat.getActionProvider(menuItem);
        actionProvider.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onOptionsItemSelected(menuItem);
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        actionProvider.setIcon(R.drawable.filter);
        actionProvider.setText(R.string.menutext1);
    }
}

特别说明一点我们CustomActionProvider中暴露的方法不能再onCreateOptionMenu中直接调用,应为ActionProvider还没有加载完成,我这里是在onWindowFocusChanged()中调用。到此我们的第一种方式介绍结束,如果有不明白的地方,可以参考严大的博客点击打开链接

  • ActionLayout定义菜单布局

第二种方式比较简单,也不需要定义actionProvider,只需要定义一个布局文件:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/text"
    android:background="?actionBarItemBackground"
    android:drawableLeft="@drawable/filter"
    android:drawablePadding="6dp"
    android:gravity="center"
    android:padding="6dp"
    android:text="@string/menutext2"
    android:textColor="@android:color/white">

</TextView>

然后在menu中使用

<?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/menu2"
        android:title="@string/menutext2"
        app:actionLayout="@layout/custom_menu"
        app:showAsAction="always" />
</menu>

与自定义CustomActionProvider相同,这里也是使用app开头,而不是android,接着是java代码:

View actionView;
MenuItem item;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_custom, menu);
    item = menu.findItem(R.id.menu2);
    actionView = item.getActionView();
    return super.onCreateOptionsMenu(menu);
}

然后是添加点击事件:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    actionView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onOptionsItemSelected(item);
        }
    });
}

如果不添加点击事件,onOptionsItemSelected()中是不会有事件响应;为什么要在onWindowFocusChanged()中添加事件的原因与上面相同,这里就不在解释。如果需要修改menu文字或者图片,可以通过ActionView获取控件修改,比如:

TextView text = actionView.findViewById(R.id.text);
text.setText("filter");
到此两种方法介绍结束,源码下载地址 点击打开链接

猜你喜欢

转载自blog.csdn.net/jy494495991/article/details/80473559
今日推荐