Android 标题栏(二)

本文详细介绍了如何在Android中使用ActionBar和Toolbar,包括设置ActionView、ActionView的展开折叠、添加ActionProvider、自定义Provider、设置ActionLayout、页面导航、设置ActionMode以及如何将Toolbar作为独立组件使用。通过实例展示了各种功能的实现,帮助开发者更好地掌握这两个组件的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       在前一篇文章Android标题栏(一)中我们已经讲解了一些属性,接下来我们继续讲解剩下的属性。

ActionBar & Toolbar

设置ActionView

       我们可以在菜单中设置ActionView,比如搜索,他是一个带图标和输入框的控件,他分别有两种不同的形态,展开和折叠。接下来我们就讲讲怎么设置ActionView。
       1.在menu菜单的item中设置actionViewClass属性:

<item
    android:id="@+id/search_icon"
    android:icon="@drawable/actionbar_search_dark_icon"
    android:title="@string/search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="ifRoom|collapseActionView">
</item>

// 注意 根据是否引用的support包,actionViewClass设置的类不同,如果是support包则设置为android.support.v7.widget.SearchView且用app来标识, 否则设置为android.widget.SearchView且用android来标识

       2:在代码中可以获取到ActionView,也可以设置ActionView:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_menu, menu);
    MenuItem search = menu.findItem(R.id.search_icon);
    // 这种方式也可以获取到ActionView
    // SearchView view = (SearchView) search.getActionView();
    // 一定要注意导入的类是否正确,要区分support和非support包中的类
    SearchView view = (SearchView) MenuItemCompat.getActionView(search);
    view.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return true;
}

       如果menu菜单中没有设置actionViewClass,也可以在代码中手动设置,search.setActionView(new SearchView(this));,上面就是获取到的SearchView,一定要注意引入的类是否正确,否则会崩溃,拿到后就可以设置查询等监听了,这里就不在演示了。

ActionView展开折叠

       我们可以对菜单添加展开折叠监听,比如搜索框

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_menu, menu);
    MenuItem search = menu.findItem(R.id.search_icon);
    // support 包调用如下方法
    MenuItemCompat.setOnActionExpandListener(search, new MenuItemCompat.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            return false;
        }

        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            return false;
        }
    });
//        
//        search.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
//            @Override
//            public boolean onMenuItemActionExpand(MenuItem item) {
//                // TODO
//                return true;
//            }
//
//            @Override
//            public boolean onMenuItemActionCollapse(MenuItem item) {
//                // TODO
//                return true;
//            }
//        });
    return true;
}

       返回true表示应该被展开或者折叠,返回false表示不应该被展开或者折叠,处理逻辑都在两个回调中。

添加ActionProvider

       1.在menu菜单中添加app:actionProviderClass属性:

<item
    android:id="@+id/plus"
    android:icon="@drawable/actionbar_plus_icon_normal"
    android:title="@string/more"
    app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
    app:showAsAction="always">
</item>

// 注意 根据是否引用的support包,actionProviderClass设置的类不同,如果是support包则设置为android.support.v7.widget.ShareActionProvider且用app来标识, 否则设置为android.widget.ShareActionProvider且用android来标识

       2. 在代码中设置

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_menu, menu);
    MenuItem plus = menu.findItem(R.id.plus);
    //support包中采用如下方法
    //MenuItemCompat.setActionProvider(plus, new ShareActionProvider(this));
    //非support中直接设置
    //plus.setActionProvider(new ShareActionProvider(this));

    //support包中采用如下方法
    ShareActionProvider provider = (ShareActionProvider) MenuItemCompat.getActionProvider(plus);
    provider.setShareIntent(getShareIntent());
    //ShareActionProvider provider = plus.getActionProvider();
    return true;
}

private Intent getShareIntent() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}

       上述就实现了分享的效果,只是需要注意的是要区分所引用的类是否是support包中的类。类型一定要正确。

自定义provider

       如果系统提供的provider不符合要求怎么办?我们还可以自定义provider。

public class PlusProvider extends ActionProvider {
    /**
     * Creates a new instance. ActionProvider classes should always implement a
     * constructor that takes a single Context parameter for inflating from menu XML.
     *
     * @param context Context for accessing resources.
     */
    public PlusProvider(Context context) {
        super(context);
    }

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        subMenu.clear();
        subMenu.add("tab1").setIcon(R.drawable.logo).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return false;
            }
        });
        subMenu.add("tab2").setIcon(R.drawable.logo).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return false;
            }
        });
    }

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

    @Override
    public boolean hasSubMenu() {
        return true;
    }
}

       上面我们自定义了一个加号的provider,hasSubMenu表示十分有子菜单,true表示有,在onPrepareSubMenu中初始化子菜单。子菜单可以设置显示文字,图标与响应点击事件。

       设置完成后,就与系统提供的provider使用方式一样。

设置ActionLayout

       设置ActionLayout可以用自定义的布局来展示菜单图标。
       1.创建一个布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:gravity="right"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.netease.study.ui.title.ActionBarActivity">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/actionbar_setting_icon"/>

</RelativeLayout>

       布局中包含了一个设置图标,之后在menu中引用

<item
    android:id="@+id/plus"
    android:icon="@drawable/actionbar_plus_icon_normal"
    android:title="@string/more"
    app:actionLayout="@layout/action_layout"
    app:showAsAction="always">
</item>

       这样就把默认的加号图标给改变成设置图标,在代码中也可以调用setActionView来更改图标。但是不建议这样做,每一个菜单都做明确的事情。

页面导航

       怎么开启页面导航?在代码中调用getActionBar(). setDisplayHomeAsUpEnabled(true)就可以开启页面导航,如果是support包中需要调用getSupportActionBar(),开启后,默认页面左上角会出现返回箭头。指示页面点击可以返回。仅仅是开启页面导航是不够的,还需要对他进行处理。

       因为返回箭头也属于ActionBar中的ActionView因此处理方式是一样的,不同是的它的id已经默认指定为android.R.id.home。因此需要在onOptionsItemSelected函数中处理id为android.R.id.home:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            break;
    }
    return super.onOptionsItemSelected(item);
}

       左上的箭头图标,我们可以在style中设置为自己的图标,也可以在代码中调用getActionBar().setHomeAsUpIndicator()来更改图标。

       一般情况下只需要关闭掉当前界面,因此直接调用finish关闭掉当前页面。但是这不是返回箭头设置的初衷,否则他与软件的返回没有任何的区别,那在什么情况下需要特殊处理呐?

       我们先来看看一个官方的图片:

这里写图片描述

       这里有一个邮件列表页面,点击其中一项,打开邮件详情,在邮件详情页可以左右导航到上一封或者下一封邮件,这样在点击左上箭头事希望能回到列表页,而软键盘返回则返回上一个页面。这种情况怎么处理?

       1.首先需要在AndroidManifest页面中对Activity设置parent属性:

// 4.1版本之前
<activity
    android:name=".ActionBarActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity">
    </meta-data>
</activity>

// 4.1版本之后
<activity
    android:name=".ActionBarActivity"
    android:parentActivityName=".MainActivity">
</activity>

       2:在代码中处理对应的逻辑:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent intent = NavUtils.getParentActivityIntent(this);
            if(intent!=null){
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                NavUtils.navigateUpTo(this, intent);
            }else{
                finish();
            }
            break;
    }
    return super.onOptionsItemSelected(item);
}

       这样就可以直接放回到列表页,不在返回上一个界面,与返回键处理是不同的。

设置ActionMode

       ActionMode是一种菜单,但是与其他菜单不一样的是,他占据的位置默认为ActionBar的位置,使用方式如下:

private void findViews() {
    View actionMode = findViewById(R.id.show_menu);
    assert actionMode != null;
    actionMode.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            ActionBarActivity.this.startActionMode(callback);
            return true;
        }
    });
}
private ActionMode.Callback callback = new ActionMode.Callback() {
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate(R.menu.action_menu1, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {

    }
};

       我在对一个view进行长按的时候,出现ActionMode菜单。

       长按前:
这里写图片描述

       长按后:
这里写图片描述

Toolbar

       如果Toolbar不当做ActionBar处理,Toolbar怎么进行设置与菜单显示?


private void setToolbar(Toolbar toolbar) {
    //setSupportActionBar(toolbar);
    toolbar.setTitle("主标题");
    toolbar.setSubtitle("副标题");
    toolbar.setLogo(R.drawable.logo);
    toolbar.inflateMenu(R.menu.action_menu);
    toolbar.setOnMenuItemClickListener(new toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            return false;
        }
    });
}

       上面演示了当不做为ActionBar时,Toolbar怎么进行设置,主要是菜单的加载方式变化。Toolbar还可以与CollapsingToolbarLayout,AppBarLayout实现不一样的标题效果。

总结

       这里主要是对ActionBar和Toolbar的使用进行了梳理,其实还有怎么对他们进行主题配置,这里就不在展开了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值