前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(二十)顶部导航栏ActionBar

Android开发笔记(二十)顶部导航栏ActionBar

作者头像
aqi00
发布2019-01-18 10:29:43
8.1K0
发布2019-01-18 10:29:43
举报
文章被收录于专栏:老欧说安卓老欧说安卓

标题栏ActionBar

ActionBar是在Android3.0之后引入的,所以Android2.x之前的版本不能直接使用ActionBar。现在ActionBar广泛用做APP的顶部导航栏,它在布局上主要分为三部分:左边是返回区域,包括logo、返回箭头、左侧标题等等;右边是菜单区域,放的是溢出菜单OverflowMenu的各菜单项;中间是条件区域,包括导航项Navigation(下拉列表与标签切换)、搜索框SearchView,以及可自定义的定制视图CustomView。 显示或者关闭ActionBar的方式有如下几种: 1、在AndroidManifest.xml中给activity设置无标题栏的主题,就关闭ActionBar。否则就显示

代码语言:javascript
复制
<activity android:theme="@android:style/Theme.Holo.NoActionBar"> 

2、在styles.xml的当前主题中加入一个项android:windowNoTitle,为true时表示关闭ActionBar;为false表示显示

代码语言:javascript
复制
<item name="android:windowNoTitle">true</item>

3、在Activity代码的setContentView之前加入下面代码,就关闭ActionBar。否则就显示

代码语言:javascript
复制
requestWindowFeature(Window.FEATURE_NO_TITLE);

4、在Activity代码中获得ActionBar实例,调用该实例的hide方法表示关闭ActionBar;调用show方法表示显示

代码语言:javascript
复制
ActionBar actionBar = getActionBar();
if (actionBar != null) {
    actionBar.hide();  //隐藏ActionBar
    actionBar.show();  //显示ActionBar
}

ActionBar的基本设置

ActionBar其上各控件的开关设置说明如下: setDisplayUseLogoEnabled : 是否在左侧返回区域显示logo,默认显示 setDisplayHomeAsUpEnabled : 是否在左侧返回区域显示返回箭头,默认不显示 setDisplayShowTitleEnabled : 是否在左侧返回区域显示左侧标题,默认显示APP名称 setTitle : 设置左侧标题的文本 setBackgroundDrawable : 设置ActionBar的背景图像 setDisplayShowCustomEnabled : 是否在中间条件区域显示定制视图 setNavigationMode : 设置导航项的样式,NAVIGATION_MODE_STANDARD表示不显示,NAVIGATION_MODE_LIST表示显示下拉列表,NAVIGATION_MODE_TABS表示显示标签切换。默认不显示 setDisplayOptions : 设置显示的选项参数,以“|”连接,各参数与设置函数的对应关系如下: DISPLAY_USE_LOGO : 对应setDisplayUseLogoEnabled DISPLAY_SHOW_HOME : 无对应函数,该参数表示需要显示左侧返回区域 DISPLAY_HOME_AS_UP : 对应setDisplayHomeAsUpEnabled DISPLAY_SHOW_TITLE : 对应setDisplayShowTitleEnabled DISPLAY_SHOW_CUSTOM : 对应setDisplayShowCustomEnabled

溢出菜单OverflowMenu

OverflowMenu其实就是把选项菜单OptionsMenu搬到了页面右上方,具体使用方法与Menu是一样的,所以就不多说了。下面列一下几个注意点: 1、菜单项的布局定义中,要把showAsAction属性设置好。该属性的取值类型主要有: ifRoom : 如果ActionBar右侧有空间,则该项直接显示在ActionBar上面,不再放入溢出菜单。 never : 从不在ActionBar上直接显示,一直放在溢出菜单里面。 always : 总是在ActionBar上显示。 withText : 如果能在ActionBar上显示,则除了显示该项的图标,还要显示该项的文字说明。 collapseActionView : 不常用,而且比较麻烦,若有兴趣可自行查阅资料。 2、Android手机一般都有物理按键,按下物理按键的菜单键,有的手机在顶部显示选项菜单而不是在右上角显示,有的手机干脆不显示任何菜单(常见于Android4.2.2以下系统)。所以为了兼容不同手机不同系统,我们需要对溢出菜单做特殊处理,将物理按键加以屏蔽,强制显示OverflowMenu。 3、放入溢出菜单的菜单项,Android默认不在菜单文字左侧显示图标,就算在菜单布局文件中设置了android:icon也不管用。所以要想在菜单列表中显示左侧图标,需要调用MenuBuilder的setOptionalIconsVisible方法(MenuBuilder在Android内核中,未开放出来,只能通过反射机制来调用)。

导航项Navigation

使用导航项需要在ActionBar中将其设置为具体模式(setNavigationMode),目前ActionBar支持两种导航模式: 1、NAVIGATION_MODE_LIST: 表示采用下拉列表模式; 2、NAVIGATION_MODE_TABS: 表示采用标签切换模式; 下拉列表模式的使用方法类似Spinner,也要设置列表文本的ArrayAdapter与监听器。不同的是Spinner的监听器继承自OnItemSelectedListener,而Navigation的监听器继承自OnNavigationListener。 标签切换模式在实际开发中用得不多,类似效果一般采用底部标签栏或者ViewPager实现。

定制视图CustomView

定制视图用于在ActionBar上显示一些个性化内容,比如说,ActionBar自带的标题文字位于左侧区域,而且也不能调整文字大小、颜色等等,如果我们想把标题文本挪到中间,还要设置文字样式的话,就得使用定制视图了。 使用定制视图需要在ActionBar中将其设置为可用(setDisplayShowCustomEnabled),同时要通过setDisplayOptions来设置DISPLAY_SHOW_CUSTOM。 定制视图的布局与普通布局一样,都在layout目录下,从布局文件中获取并修改完成视图后,调用ActionBar的setCustomView方法就完成了定制。 另外,更换左侧返回区域的返回箭头图标,可通过ActionBar的setIcon来实现。但该方法在Android4.4.2之后才支持,之前版本的系统仍然不支持定制左侧返回图标。

搜索框SearchView

搜索框有些复杂,实现步骤大致如下: 1、在菜单布局文件中定义搜索项:

代码语言:javascript
复制
    <item
        android:id="@+id/menu_search"
        android:orderInCategory="1"
        android:icon="@drawable/ic_search"
        android:showAsAction="ifRoom"
        android:title="搜索"
        android:actionViewClass="android.widget.SearchView" />

2、在res\xml目录下新建searchable.xml,设置搜索框的样式:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/please_input"
    android:inputType="text"
    android:searchButtonText="@string/search" />

3、在AndroidManifest.xml中加入一个搜索结果activity的定义,需要指定action和meta-data,例如:

代码语言:javascript
复制
        <activity android:name=".SearchResultActvity" android:label="@string/app_name" >
            <intent-filter> 
                <action android:name="android.intent.action.SEARCH"/>
            </intent-filter> 
            <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
        </activity>

4、在菜单代码中初始化搜索框,并关联搜索动作对应的activity(本例中的activity是SearchResultActvity)

代码语言:javascript
复制
	private void initSearchView(Menu menu) {
	    SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
	    if(searchView == null){
	        Log.d(TAG, "Fail to get SearchView.");
	    } else {
	    	//设置搜索框默认自动缩小为图标
	    	searchView.setIconifiedByDefault(true);
	    	//设置是否显示搜索按钮。搜索按钮只显示一个箭头图标,Android暂不支持显示文本。
	    	//查看Android源码,搜索按钮用的控件是ImageView,所以。。。
	    	searchView.setSubmitButtonEnabled(true);
	    	//设置搜索框内的默认显示的提示文本
	    	//searchView.setQueryHint(getResources().getString(R.string.please_input));
	    	
	        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
	        //关联搜索结果的activity
	        ComponentName cn = new ComponentName(this, SearchResultActvity.class);
	        //从activity中获取相关搜索信息,就是searchable的xml设置
	        SearchableInfo info = searchManager.getSearchableInfo(cn); 
	        if(info == null){ 
	            Log.d(TAG, "Fail to get SearchResultActvity."); 
	        }      
	        //将activity的搜索信息与search view关联
	        searchView.setSearchableInfo(info); 
	    }
	}

5、编写搜索结果activity的代码,其中提取搜索关键字的代码片段如下:

代码语言:javascript
复制
        if(intent == null) {
            return; 
        } else {
            //如果是通过ACTION_SEARCH来调用,即如果通过搜索调用
            if(Intent.ACTION_SEARCH.equals(intent.getAction())){
            	//获取搜索内容
                String queryString = intent.getStringExtra(SearchManager.QUERY);
                tv_search_result.setText("您输入的搜索文字是:"+queryString);
            }  
        }

代码例子

下面是几个导航栏效果的代码例子 原生导航代码,包括溢出菜单和导航项

代码语言:javascript
复制
import java.util.Date;

import com.example.exmactionbar.util.Utils;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class OriginActivity extends Activity {
	private static final String TAG = "OriginActivity";
	private TextView tv_origin;
	private String[] mDescArray = {"标点时间", "标点日期", "中文时间", "中文日期"};
	private String[] mmFormatArray = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd",
									"yyyy年MM月dd日HH时mm分ss秒", "yyyy年MM月dd日"};
	private String mFormat = mmFormatArray[0];
	private Date mNowTime = new Date();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_origin);
		tv_origin = (TextView) findViewById(R.id.tv_origin);
		getActionBar("原生页", R.drawable.actionbar_gradient_blue).show();
	}

	@SuppressLint("InflateParams")
	private ActionBar getActionBar(String title, int bgId) {
		ActionBar actionBar = this.getActionBar();
		if (actionBar != null) {
			//无论系统版本为何,无论有无物理按键,都强制显示选项菜单
			Utils.forceShowOverflowMenu(this);
			actionBar.setDisplayShowTitleEnabled(true);
			actionBar.setDisplayHomeAsUpEnabled(true);
			actionBar.setDisplayShowHomeEnabled(false);
			actionBar.setDisplayShowCustomEnabled(false);
			actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE|ActionBar.DISPLAY_HOME_AS_UP);
			if (bgId > 0) {
				actionBar.setBackgroundDrawable(getResources().getDrawable(bgId));
			}
			actionBar.setTitle(title);
			//允许在导航栏上显示下拉框,另一种NAVIGATION_MODE_TABS表示标签页切换
			actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
			ArrayAdapter<String> adapter = new ArrayAdapter<String>(
					this, R.layout.spinner_item, mDescArray);
			adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
			actionBar.setListNavigationCallbacks(adapter, new navigationListener());
		} else {
			Toast.makeText(this, "无法获得ActionBar", Toast.LENGTH_SHORT).show();
		}
		return actionBar;
	}

	class navigationListener implements OnNavigationListener {
		@Override
		public boolean onNavigationItemSelected(int itemPosition, long itemId) {
			mFormat = mmFormatArray[itemPosition];
			tv_origin.setText("当前格式时间: "+Utils.getFormatDateTime(mNowTime, mFormat));
			return false;
		}
	}
	
    @Override  
    public boolean onMenuOpened(int featureId, Menu menu) {  
    	//显示菜单项左侧的图标
        Utils.setOverflowIconVisible(featureId, menu);  
        return super.onMenuOpened(featureId, menu);  
    }  
  
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == android.R.id.home) {
			finish();
		} else if (id == R.id.menu_refresh) {
			mNowTime = new Date();
			tv_origin.setText("当前刷新时间: "+Utils.getFormatDateTime(mNowTime, mFormat));
			return true;
		} else if (id == R.id.menu_about) {
			Toast.makeText(this, "这个是顶部导航栏的演示demo", Toast.LENGTH_LONG).show();
			return true;
		} else if (id == R.id.menu_quit) {
			finish();
		}
		return super.onOptionsItemSelected(item);
	}

}

定制导航代码,包括溢出菜单和定制视图

代码语言:javascript
复制
import com.example.exmactionbar.util.Utils;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class CustomActivity extends Activity {
	private static final String TAG = "CustomActivity";
	private TextView tv_custom;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_custom);
		tv_custom = (TextView) findViewById(R.id.tv_custom);
		getActionBar("定制标题", R.drawable.actionbar_gradient_red).show();
	}

	@SuppressLint("InflateParams")
	private ActionBar getActionBar(String title, int bgId) {
		ActionBar actionBar = this.getActionBar();
		if (actionBar != null) {
			//无论系统版本为何,无论有无物理按键,都强制显示选项菜单
			Utils.forceShowOverflowMenu(this);
			actionBar.setDisplayShowTitleEnabled(false);
			actionBar.setDisplayHomeAsUpEnabled(true);
			actionBar.setDisplayShowHomeEnabled(true);
			actionBar.setDisplayShowCustomEnabled(true);
			if (bgId > 0) {
				actionBar.setBackgroundDrawable(getResources().getDrawable(bgId));
			}
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
				actionBar.setIcon(R.drawable.back_btn);
				actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM|ActionBar.DISPLAY_SHOW_HOME);
			} else {
				actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM|ActionBar.DISPLAY_SHOW_HOME|ActionBar.DISPLAY_HOME_AS_UP);
			}
			ActionBar.LayoutParams lp =new ActionBar.LayoutParams(
					ActionBar.LayoutParams.MATCH_PARENT,
					ActionBar.LayoutParams.WRAP_CONTENT,
					Gravity.CENTER);
			View v_titlebar = this.getLayoutInflater().inflate(R.layout.action_bar_title, null);
			actionBar.setCustomView(v_titlebar, lp);
			TextView tv_title = (TextView) v_titlebar.findViewById(R.id.tv_title);
			tv_title.setText(title);
		} else {
			Toast.makeText(this, "无法获得ActionBar", Toast.LENGTH_SHORT).show();
		}
		
		return actionBar;
	}

    @Override  
    public boolean onMenuOpened(int featureId, Menu menu) {  
    	//显示菜单项左侧的图标
        Utils.setOverflowIconVisible(featureId, menu);  
        return super.onMenuOpened(featureId, menu);  
    }  
  
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == android.R.id.home) {
			finish();
		} else if (id == R.id.menu_refresh) {
			tv_custom.setText("当前刷新时间: "+Utils.getNowDateTime("yyyy-MM-dd HH:mm:ss"));
			return true;
		} else if (id == R.id.menu_about) {
			Toast.makeText(this, "这个是顶部导航栏的演示demo", Toast.LENGTH_LONG).show();
			return true;
		} else if (id == R.id.menu_quit) {
			finish();
		}
		return super.onOptionsItemSelected(item);
	}
}

搜索导航代码,包括溢出菜单和搜索框

代码语言:javascript
复制
import com.example.exmactionbar.util.Utils;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;

public class SearchActivity extends Activity {
	private static final String TAG = "SearchActivity";
	private TextView tv_search;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_search);
		tv_search = (TextView) findViewById(R.id.tv_search);
		getActionBar(this, "搜索页", R.drawable.actionbar_gradient_blue).show();
	}

	@SuppressLint("InflateParams")
	public static ActionBar getActionBar(Activity act, String title, int bgId) {
		ActionBar actionBar = act.getActionBar();
		if (actionBar != null) {
			actionBar.setDisplayShowTitleEnabled(true);
			actionBar.setDisplayHomeAsUpEnabled(true);
			actionBar.setDisplayShowHomeEnabled(false);
			actionBar.setDisplayShowCustomEnabled(false);
			actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE|ActionBar.DISPLAY_HOME_AS_UP);
			if (bgId > 0) {
				actionBar.setBackgroundDrawable(act.getResources().getDrawable(bgId));
			}
			actionBar.setTitle(title);
		} else {
			Toast.makeText(act, "无法获得ActionBar", Toast.LENGTH_SHORT).show();
		}
		return actionBar;
	}
	
	private void initSearchView(Menu menu) {
	    SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
	    if(searchView == null){
	        Log.d(TAG, "Fail to get SearchView.");
	    } else {
	    	//设置搜索框默认自动缩小为图标
	    	searchView.setIconifiedByDefault(true);
	    	//设置是否显示搜索按钮。搜索按钮只显示一个箭头图标,Android暂不支持显示文本。
	    	//查看Android源码,搜索按钮用的控件是ImageView,所以。。。
	    	searchView.setSubmitButtonEnabled(true);
	    	//设置搜索框内的默认显示的提示文本
	    	//searchView.setQueryHint(getResources().getString(R.string.please_input));
	    	
	        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
	        //关联搜索结果的activity
	        ComponentName cn = new ComponentName(this, SearchResultActvity.class);
	        //从activity中获取相关搜索信息,就是searchable的xml设置
	        SearchableInfo info = searchManager.getSearchableInfo(cn); 
	        if(info == null){ 
	            Log.d(TAG, "Fail to get SearchResultActvity."); 
	        }      
	        //将activity的搜索信息与search view关联
	        searchView.setSearchableInfo(info); 
	    }
	}

    @Override  
    public boolean onMenuOpened(int featureId, Menu menu) {  
    	//显示菜单项左侧的图标
        Utils.setOverflowIconVisible(featureId, menu);  
        return super.onMenuOpened(featureId, menu);  
    }  
  
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.search, menu);
		//对搜索框做初始化
		initSearchView(menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == android.R.id.home) {
			finish();
		} else if (id == R.id.menu_about) {
			Toast.makeText(this, "这个是顶部导航栏的演示demo", Toast.LENGTH_LONG).show();
			return true;
		} else if (id == R.id.menu_quit) {
			finish();
		}
		return super.onOptionsItemSelected(item);
	}
}

下面是顶部导航栏三种方式的效果图 原生导航

定制导航

搜索导航

点击下载本文用到的顶部导航栏三种方式的代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年12月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 标题栏ActionBar
  • ActionBar的基本设置
  • 溢出菜单OverflowMenu
  • 导航项Navigation
  • 定制视图CustomView
  • 搜索框SearchView
  • 代码例子
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档