Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477


本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文。

http://developer.android.com/guide/topics/ui/actionbar.html


Action Bar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,它标识了用户当前操作界面的位置,并提供了额外的用户动作、界面导航等功能。使用ActionBar的好处是,它可以给提供一种全局统一的UI界面,使得用户在使用任何一款软件时都懂得该如何操作,并且ActionBar还可以自动适应各种不同大小的屏幕。下面是一张使用ActionBar的界面截图:




其中,[1]是ActionBar的图标,[2]是两个action按钮,[3]是overflow按钮。


由于Action Bar是在3.0以后的版本中加入的,如果想在2.x的版本里使用ActionBar的话则需要引入Support Library,不过3.0之前版本的市场占有率已经非常小了,这里简单起见我们就不再考虑去做向下兼容,而是只考虑4.0以上版本的用法。


添加和移除Action Bar


ActionBar的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就可以了,而使用Eclipse创建的项目自动就会将Application的theme指定成Theme.Holo,所以ActionBar默认都是显示出来的。新建一个空项目并运行,效果如下图所示:




而如果想要移除ActionBar的话通常有两种方式,一是将theme指定成Theme.Holo.NoActionBar,表示使用一个不包含ActionBar的主题,二是在Activity中调用以下方法:

ActionBar actionBar = getActionBar();
actionBar.hide();

现在重新运行一下程序,就可以看到ActionBar不再显示了,如下图所示:




修改Action Bar的图标和标题


默认情况下,系统会使用<application>或者<activity>中icon属性指定的图片来作为ActionBar的图标,但是我们也可以改变这一默认行为。如果我们想要使用另外一张图片来作为ActionBar的图标,可以在<application>或者<activity>中通过logo属性来进行指定。比如项目的res/drawable目录下有一张weather.png图片,就可以在AndroidManifest.xml中这样指定:
<activity
    android:name="com.example.actionbartest.MainActivity"
    android:logo="@drawable/weather" >
</activity>
现在重新运行一下程序,效果如下图所示:



OK,ActionBar的图标已经修改成功了,那么标题中的内容该怎样修改呢?其实也很简单,使用label属性来指定一个字符串就可以了,如下所示:
<activity
    android:name="com.example.actionbartest.MainActivity"
    android:label="天气"
    android:logo="@drawable/weather" >
</activity>
现在重新运行一下程序,结果如下图所示:



添加Action按钮


ActionBar还可以根据应用程序当前的功能来提供与其相关的Action按钮,这些按钮都会以图标或文字的形式直接显示在ActionBar上。当然,如果按钮过多,ActionBar上显示不完,多出的一些按钮可以隐藏在overflow里面(最右边的三个点就是overflow按钮),点击一下overflow按钮就可以看到全部的Action按钮了。

当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法来取出所有的Action按钮,我们只需要在这个方法中去加载一个menu资源,并把所有的Action按钮都定义在资源文件里面就可以了。

那么我们先来看下menu资源文件该如何定义,代码如下所示:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.actionbartest.MainActivity" >

    <item
        android:id="@+id/action_compose"
        android:icon="@drawable/ic_action_compose"
        android:showAsAction="always"
        android:title="@string/action_compose"/>
    <item
        android:id="@+id/action_delete"
        android:icon="@drawable/ic_action_delete"
        android:showAsAction="always"
        android:title="@string/action_delete"/>
    <item
        android:id="@+id/action_settings"
        android:icon="@drawable/ic_launcher"
        android:showAsAction="never"
        android:title="@string/action_settings"/>

</menu>
可以看到,这里我们通过三个<item>标签定义了三个Action按钮。<item>标签中又有一些属性,其中id是该Action按钮的唯一标识符,icon用于指定该按钮的图标,title用于指定该按钮可能显示的文字(在图标能显示的情况下,通常不会显示文字),showAsAction则指定了该按钮显示的位置,主要有以下几种值可选:always表示永远显示在ActionBar中,如果屏幕空间不够则无法显示,ifRoom表示屏幕空间够的情况下显示在ActionBar中,不够的话就显示在overflow中,never则表示永远显示在overflow中。
接着,重写Activity的onCreateOptionsMenu()方法,代码如下所示:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.main, menu);
	return super.onCreateOptionsMenu(menu);
}
这部分代码很简单,仅仅是调用了MenuInflater的inflate()方法来加载menu资源就可以了。现在重新运行一下程序,结果如下图所示:



可以看到,action_compose和action_delete这两个按钮已经在ActionBar中显示出来了,而action_settings这个按钮由于showAsAction属性设置成了never,所以被隐藏到了overflow当中,只要点击一下overflow按钮就可以看到它了。

这里我们注意到,显示在ActionBar上的按钮都只有一个图标而已,我们在title中指定的文字并没有显示出来。没错,title中的内容通常情况下只会在overflow中显示出来,ActionBar中由于屏幕空间有限,默认是不会显示title内容的。但是出于以下几种因素考虑,即使title中的内容无法显示出来,我们也应该给每个item中都指定一个title属性:
  • 当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了。
  • 如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。


响应Action按钮的点击事件


当用户点击Action按钮的时候,系统会调用Activity的onOptionsItemSelected()方法,通过方法传入的MenuItem参数,我们可以调用它的getItemId()方法和menu资源中的id进行比较,从而辨别出用户点击的是哪一个Action按钮,比如:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
	case R.id.action_compose:
		Toast.makeText(this, "Compose", Toast.LENGTH_SHORT).show();
		return true;
	case R.id.action_delete:
		Toast.makeText(this, "Delete", Toast.LENGTH_SHORT).show();
		return true;
	case R.id.action_settings:
		Toast.makeText(this, "Settings", Toast.LENGTH_SHORT).show();
		return true;
	default:
		return super.onOptionsItemSelected(item);
	}
}
可以看到,我们让每个Action按钮被点击的时候都弹出一个Toast,现在重新运行一下代码,结果如下图所示:




通过Action Bar图标进行导航


启用ActionBar图标导航的功能,可以允许用户根据当前应用的位置来在不同界面之间切换。比如,A界面展示了一个列表,点击某一项之后进入了B界面,这时B界面就应该启用ActionBar图标导航功能,这样就可以回到A界面。

我们可以通过调用setDisplayHomeAsUpEnabled()方法来启用ActionBar图标导航功能,比如:
@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setTitle("天气");
	setContentView(R.layout.activity_main);
	ActionBar actionBar = getActionBar();
	actionBar.setDisplayHomeAsUpEnabled(true);
}
现在重新运行一下程序,结果如下图所示:



可以看到,在ActionBar图标的左侧出现了一个向左的箭头,通常情况下这都表示返回的意思,因此最简单的实现就是在它的点击事件里面加入finish()方法就可以了,如下所示:
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			finish();
			return true;
		……
		}
	}
当点击ActionBar图标的时候,系统同样会调用onOptionsItemSelected()方法,并且此时的itemId是android.R.id.home,所以finish()方法也就是加在这里的了。
现在看上去,ActionBar导航和Back键的功能貌似是一样的。没错,如果我们只是简单地finish了一下,ActionBar导航和Back键的功能是完全一样的,但ActionBar导航的设计初衷并不是这样的,它和Back键的功能还是有一些区别的,举个例子吧。



上图中的Conversation List是收件箱的主界面,现在我们点击第一封邮件会进入到Conversation1 details界面,然后点击下一封邮件会进入到Conversation 2 details界面,再点击下一封邮箱会进入到Conversation3 details界面。好的,这个时候如果我们按下Back键,应该会回到Conversation 2 details界面,再按一次Back键应该回到Conversation1 details界面,再按一次Back键才会回到Conversation List。而ActionBar导航则不应该表现出这种行为,无论我们当前在哪一个Conversation details界面,点击一下导航按钮都应该回到Conversation List界面才对。

这就是ActionBar导航和Back键在设计上的区别,那么该怎样才能实现这样的功能呢?其实并不复杂,实现标准的ActionBar导航功能只需三步走。

第一步我们已经实现了,就是调用setDisplayHomeAsUpEnabled()方法,并传入true。

第二步需要在AndroidManifest.xml中配置父Activity,如下所示:
<activity
    android:name="com.example.actionbartest.MainActivity"
    android:logo="@drawable/weather" >
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.actionbartest.LaunchActivity" />
</activity>
可以看到,这里通过meta-data标签指定了MainActivity的父Activity是LaunchActivity,在Android 4.1版本之后,也可以直接使用android:parentActivityName这个属性来进行指定,如下所示:
<activity
    android:name="com.example.actionbartest.MainActivity"
    android:logo="@drawable/weather"
    android:parentActivityName="com.example.actionbartest.LaunchActivity" >
</activity>
第三步则需要对android.R.id.home这个事件进行一些特殊处理,如下所示:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
	case android.R.id.home:
		Intent upIntent = NavUtils.getParentActivityIntent(this);
		if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
			TaskStackBuilder.create(this)
					.addNextIntentWithParentStack(upIntent)
					.startActivities();
		} else {
			upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			NavUtils.navigateUpTo(this, upIntent);
		}
		return true;
        ......
	}
}
其中,调用NavUtils.getParentActivityIntent()方法可以获取到跳转至父Activity的Intent,然后如果父Activity和当前Activity是在同一个Task中的,则直接调用navigateUpTo()方法进行跳转,如果不是在同一个Task中的,则需要借助TaskStackBuilder来创建一个新的Task。

这样,就按照标准的规范成功实现ActionBar导航的功能了。

添加Action View


ActionView是一种可以在ActionBar中替换Action按钮的控件,它可以允许用户在不切换界面的情况下通过ActionBar完成一些较为丰富的操作。比如说,你需要完成一个搜索功能,就可以将SeachView这个控件添加到ActionBar中。

为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件,例如可以使用如下方式添加SearchView:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_action_search"
        android:actionViewClass="android.widget.SearchView"
        android:showAsAction="ifRoom|collapseActionView"
        android:title="@string/action_search" />
    ......

</menu>
注意在showAsAction属性中我们还声明了一个collapseActionView,这个值表示该控件可以被合并成一个Action按钮。
现在重新运行一下程序,效果如下图所示:



OK,果然有一个搜索样式的Action按钮出现了,现在点击一下这个搜索按钮,效果如下图所示:



可以看到,这时SearchView就会展开占满整个ActionBar,而其它的Action按钮由于将showAsAction属性设置成了ifRoom,此时都会隐藏到overflow当中。

如果你还希望在代码中对SearchView的属性进行配置(比如添加监听事件等),完全没有问题,只需要在onCreateOptionsMenu()方法中获取该ActionView的实例就可以了,代码如下所示:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.main, menu);
	MenuItem searchItem = menu.findItem(R.id.action_search);
	SearchView searchView = (SearchView) searchItem.getActionView();
	// 配置SearchView的属性
	......
	return super.onCreateOptionsMenu(menu);
}
在得到了SearchView的实例之后,就可以任意地配置它的各种属性了。关于SearchView的更多详细用法,可以参考官方文档  http://developer.android.com/guide/topics/search/search-dialog.html 。

除此之外,有些程序可能还希望在ActionView展开和合并的时候显示不同的界面,其实我们只需要去注册一个ActionView的监听器就能实现这样的功能了,代码如下所示:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.main, menu);
	MenuItem searchItem = menu.findItem(R.id.action_search);
	searchItem.setOnActionExpandListener(new OnActionExpandListener() {
		@Override
		public boolean onMenuItemActionExpand(MenuItem item) {
			Log.d("TAG", "on expand");
			return true;
		}
		
		@Override
		public boolean onMenuItemActionCollapse(MenuItem item) {
			Log.d("TAG", "on collapse");
			return true;
		}
	});
	return super.onCreateOptionsMenu(menu);
}
可以看到,调用MenuItem的setOnActionExpandListener()方法就可以注册一个监听器了,当SearchView展开的时候就会回调onMenuItemActionExpand()方法,当SearchView合并的时候就会调用onMenuItemActionCollapse()方法,我们在这两个方法中进行相应的UI操作就可以了。

Overflow按钮不显示的情况


虽然现在我们已经掌握了不少ActionBar的用法,但是当你真正去使用它的时候还是可能会遇到各种各样的问题,比如很多人都会碰到overflow按钮不显示的情况。明明是同样的一份代码,overflow按钮在有些手机上会显示,而在有些手机上偏偏就不显示,这是为什么呢?后来我总结了一下,overflow按钮的显示情况和手机的硬件情况是有关系的,如果手机没有物理Menu键的话,overflow按钮就可以显示,如果有物理Menu键的话,overflow按钮就不会显示出来。比如我们启动一个有Menu键的模拟器,然后将代码运行到该模拟器上,结果如下图所示:



可以看到,ActionBar最右边的overflow按钮不见了!那么此时我们如何查看隐藏在overflow中的Action按钮呢?其实非常简单,按一下Menu键,隐藏的内容就会从底部出来了,如下图所示:



看到这里相信不少朋友都想吐槽一下了,这显然是一种非常蛋疼的设计,在不同手机上竟然显示了不同的界面,而且操作方法也完全不一样,这样会给用户一种非常不习惯的感觉。话说Google为什么要把ActionBar的overflow设计成这样我也不太理解,但是我们还是有办法改变这一默认行为的。

实际上,在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手机有没有物理Menu键的。当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了,代码如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
	......
	setOverflowShowingAlways();
}

private void setOverflowShowingAlways() {
	try {
		ViewConfiguration config = ViewConfiguration.get(this);
		Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
		menuKeyField.setAccessible(true);
		menuKeyField.setBoolean(config, false);
	} catch (Exception e) {
		e.printStackTrace();
	}
}
这里我们在onCreate()方法的最后调用了setOverflowShowingAlways()方法,而这个方法的内部就是使用反射的方式将sHasPermanentMenuKey的值设置成false,现在重新运行一下代码,结果如下图所示:



可以看到,即使是在有Menu键的手机上,也能让overflow按钮显示出来了,这样就可以大大增加我们软件界面和操作的统一性。

让Overflow中的选项显示图标


如果你点击一下overflow按钮去查看隐藏的Action按钮,你会发现这部分Action按钮都是只显示文字不显示图标的,如下图所示:



这是官方的默认效果,Google认为隐藏在overflow中的Action按钮都应该只显示文字。当然,如果你认为这样不够美观,希望在overflow中的Action按钮也可以显示图标,我们仍然可以想办法来改变这一默认行为。

其实,overflow中的Action按钮应不应该显示图标,是由MenuBuilder这个类的setOptionalIconsVisible方法来决定的,如果我们在overflow被展开的时候给这个方法传入true,那么里面的每一个Action按钮对应的图标就都会显示出来了。调用的方法当然仍然是用反射了,代码如下所示:
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
	if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
		if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
			try {
				Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
				m.setAccessible(true);
				m.invoke(menu, true);
			} catch (Exception e) {
			}
		}
	}
	return super.onMenuOpened(featureId, menu);
}
可以看到,这里我们重写了一个onMenuOpened()方法,当overflow被展开的时候就会回调这个方法,接着在这个方法的内部通过返回反射的方法将MenuBuilder的setOptionalIconsVisible变量设置为true就可以了。

现在重新运行一下代码,结果如下图所示:



好了,目前为止我们已经把ActionBar的基础知识介绍完了,那么今天的讲解就到这里,下篇文章中我会带领大家一起更深入地了解ActionBar,感兴趣的朋友请继续阅读  Android ActionBar完全解析,使用官方推荐的最佳导航栏(下)

关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

微信扫一扫下方二维码即可关注:

        

  • 309
    点赞
  • 700
    收藏
    觉得还不错? 一键收藏
  • 144
    评论
目录 第1章 Android计算平台简介  1.1 面向新PC的全新平台  1.2 Android的历史  1.3 Dalvik VM剖析  1.4 理解Android软件栈  1.5 使用Android SDK开发最终用户应用程序  1.5.1 Android模拟器  1.5.2 Android UI  1.5.3 Android基础组件  1.5.4 高级UI概念  1.5.5 Android Service组件  1.5.6 Android媒体和电话组件  1.5.7 Android Java包  1.6 利用Android源代码  1.7 本书的示例项目  1.8 小结  第2章 设置开发环境  2.1 设置环境  2.1.1 下载JDK 6  2.1.2 下载Eclipse 3.6  2.1.3 下载Android SDK  2.1.4 命令行窗口  2.1.5 安装ADT  2.2 了解基本组件  2.2.1 View  2.2.2 Activity  2.2.3 Intent  2.2.4 ContentProvider  2.2.5 Service  2.2.6 AndroidManifest.xml  2.2.7 AVD  2.3 Hello World!  2.4 AVD  2.5 剖析Android应用程序的结构  2.6 分析Notepad应用程序  2.6.1 加载和运行Notepad应用程序  2.6.2 分解应用程序  2.7 了解应用程序生命周期  2.8 调试应用程序  2.8.1 启动模拟器  2.8.2 StrictMode  2.8.3 参考资料  2.9 小结  第3章 使用Android资源  3.1 资源  3.1.1 字符串资源  3.1.2 布局资源  3.1.3 资源引用语法  3.1.4 定义资源ID供以后使用  3.1.5 已编译和未编译的Android资源  3.2 Android关键资源  3.3 使用任意XML资源文件  3.4 使用原始资源  3.5 使用资产  3.6 了解资源目录结构  3.7 资源和配置更改  3.8 参考资料URL  3.9 小结  第4章 ContentProvider  4.1 探索Android内置的ContentProvider  4.2 ContentProvider的架构  4.3 实现ContentProvider  4.4 练习图书提供程序  4.4.1 添加图书  4.4.2 删除图书  4.4.3 获取图书数量  4.4.4 显示图书列表  4.5 资源  4.6 小结  第5章 Intent  5.1 Android Intent基础知识  5.2 Android中可用的Intent  5.3 Intent的组成  5.3.1 Intent和数据URI  5.3.2 一般操作  5.3.3 使用extra信息  5.3.4 使用组件直接调用活动  5.3.5 Intent类别  5.3.6 将Intent解析为组件的规则  5.4 练习使用ACTION_PICK  5.5 练习使用GET_CONTENT操作  5.6 挂起的Intent  5.7 资源  5.8 小结  第6章 构建用户界面和使用控件  6.1 Android中的UI开发  6.1.1 完全利用代码来构建UI  6.1.2 完全使用XML构建UI  6.1.3 使用XML结合代码构建UI  6.2 Android中的常见控件  6.2.1 文本控件  6.2.2 按钮控件  6.2.3 ImageView控件  6.2.4 日期和时间控件  6.2.5 MapView控件  6.3 适配器  6.3.1 SimpleCursorAdapter  6.3.2 了解ArrayAdapter  6.4 结合使用适配器和AdapterView  6.4.1 基本的列表控件:ListView  6.4.2 GridView控件  6.4.3 Spinner控件  6.4.4 Gallery控件  6.4.5 创建自定义适配器  6.4.6 Android中的其他控件  6.5 样式和主题  6.5.1 使用样式  6.5.2 使用主题  6.6 布局管理器  6.6.1 LinearLayout布局管理器  6.6.2 TableLayout布局管理器  6.6.3 RelativeLayout布局管理器  6.6.4 FrameLayout布局管理器  6.6.5 为各种设备配置自定义布局  6.7 使用Hierarchy Viewer调试和优化布局  6.8 参考资料  6.9 小结  第7章 使用菜单  7.1 Android菜单  7.1.1 创建菜单  7.1.2 使用菜单组  7.2 响应菜单项  7.3 创建测试工具来测试菜单  7.4 使用其他菜单类型  7.4.1 展开的菜单  7.4.2 使用图标菜单  7.4.3 使用子菜单  7.4.4 配置系统菜单  7.4.5 使用上下文菜单  7.4.6 使用交替菜单  7.4.7 使用菜单响应数据变化  7.5 通过XML文件加载菜单  7.5.1 XML菜单资源文件的结构  7.5.2 填充XML菜单资源文件  7.5.3 响应基于XML的菜单项  7.5.4 其他XML菜单标记简介  7.6 资源  7.7 小结  第8章 使用对话框  8.1 使用Android中的对话框  8.1.1 设计提醒对话框  8.1.2 设计提示对话框  8.1.3 Android对话框的特性  8.1.4 重新设计提示对话框  8.2 使用托管对话框  8.2.1 理解托管对话框协议  8.2.2 将非托管对话框重新转换为托管对话框  8.2.3 简化托管对话框协议  8.3 使用Toast  8.4 资源  8.5 小结  第9章 管理和组织首选项  9.1 探索首选项框架  9.1.1 ListPreference  9.1.2 CheckBoxPreference  9.1.3 EditTextPreference  9.1.4 RingtonePreference  9.2 组织首选项  9.3 以编程方式操作首选项  9.4 使用首选项保存状态  9.5 参考资料  9.6 小结  第10章 探索安全性和权限  10.1 理解Android安全性模型  10.1.1 安全性概念概述  10.1.2 为部署签名应用程序  10.2 执行运行时安全性检查  10.2.1 进程边界上的安全性  10.2.2 声明和使用权限  10.2.3 理解和使用自定义权限  10.2.4 理解和使用URI权限  10.3 参考资料  10.4 小结  第11章 构建和使用服务  11.1 使用HTTP服务  11.1.1 将HttpClient用于HTTPGET请求  11.1.2 将HttpClient用于HTTPPOST请求(多部分POST请求示例)  11.1.3 SOAP、JSON和XML分析程序  11.1.4 处理异常  11.1.5 解决多线程问题  11.1.6 有趣的超时  11.1.7 使用HttpURLConnection  11.1.8 使用AndroidHttpClient  11.1.9 使用后台线程(AsyncTask)  11.1.10 使用AsyncTask处理配置更改  11.1.11 使用DownloadManager获取文件  11.2 使用Android服务  11.2.1 Android中的服务  11.2.2 本地服务  11.2.3 AIDL服务  11.2.4 在AIDL中定义服务接口  11.2.5 实现AIDL接口  11.2.6 从客户端应用程序调用服务  11.2.7 向服务传递复杂的类型  11.3 使用服务的真实示例  11.3.1 Google翻译API  11.3.2 使用Google翻译API  11.4 参考资料  11.5 小结  第12章 包  12.1 包和进程  12.1.1 包规范的细节  12.1.2 将包名称转换为进程名称  12.1.3 列出安装的包  12.1.4 通过包浏览器删除包  12.2 包签名过程回顾  12.2.1 理解数字签名:场景1  12.2.2 理解数字签名:场景2  12.2.3 一种理解数字签名的模式  12.2.4 数字签名执行方式  12.2.5 签名过程的影响  12.3 在包之间共享数据  12.3.1 共享用户ID的性质  12.3.2 共享数据的代码模式  12.4 库项目  12.4.1 库项目的概念  12.4.2 库项目的性质  12.4.3 创建库项目  12.4.4 创建使用库的Android项目  12.5 参考资料  12.6 小结  第13章 处理程序  13.1 Android组件和线程  13.1.1 活动在主线程上运行  13.1.2 广播接收程序在主线程上运行  13.1.3 服务在主线程上运行  13.1.4 ContentProvider在主线程上运行  13.1.5 单一主线程的影响  13.1.6 线程池、ContentProvider、外部服务组件  13.1.7 线程实用程序:发现线程  13.2 处理程序  13.2.1 持有主线程的影响  13.2.2 使用处理程序延迟主线程上的工作  13.2.3 延迟工作的处理程序源代码示例  13.2.4 构造合适的Message对象  13.2.5 将Message对象发送给队列  13.2.6 响应handleMessage回调  13.3 使用工作线程  13.3.1 从菜单调用工作线程  13.3.2 在工作线程与主线程之间通信  13.3.3 线程行为概述  13.4 处理程序示例驱动程序类  13.4.1 驱动程序活动文件  13.4.2 布局文件  13.4.3 菜单文件  13.4.4 描述文件  13.5 组件和进程寿命  13.5.1 活动生命周期  13.5.2 服务生命周期  13.5.3 接收程序生命周期  13.5.4 提供程序生命周期  13.6 代码编译说明  13.6.1 从ZIP文件创建项目  13.6.2 从代码清单创建项目  13.7 参考资料  13.8 小结  第14章 广播接收程序和长期运行的服务  14.1 广播接收程序  14.1.1 发送广播  14.1.2 编写简单的接收程序:示例代码  14.1.3 在描述文件中注册接收程序  14.1.4 发送测试广播  14.1.5 容纳多个接收程序  14.1.6 进程外接收程序项目  14.2 从接收程序使用通知  14.2.1 通过通知管理器监控通知  14.2.2 发送通知  14.3 长期运行的接收程序和服务  14.3.1 长期运行的广播接收程序协议  14.3.2 IntentService  14.3.3 IntentService源代码  14.4 为广播接收程序扩展IntentService  14.4.1 长期运行的广播服务抽象  14.4.2 长期运行的接收程序  14.4.3 使用LightedGreenRoom抽象唤醒锁  14.5 长期运行的服务的实现  14.5.1 非粘滞性服务的细节  14.5.2 粘滞性服务的细节  14.5.3 非粘滞性的变体:重传送(redeliver)Intent  14.5.4 在onStartCommand中指定服务标志  14.5.5 挑选合适的粘滞性  14.5.6 从两个位置控制唤醒锁  14.5.7 长期运行的服务的实现  14.5.8 测试长期运行的服务  14.6 代码编译说明  14.6.1 从ZIP文件创建项目  14.6.2 通过代码清单创建项目  14.7 参考资料  14.8 小结  第15章 闹钟管理器  15.1 闹钟管理器基本知识:设置一个简单的闹钟  15.1.1 获取闹钟管理器  15.1.2 设置闹钟时间  15.1.3 设置闹钟接收程序  15.1.4 创建适合闹钟的PendingIntent  15.1.5 设置闹钟  15.1.6 测试项目  15.2 探索其他闹钟管理器场景  15.2.1 设置重复闹钟  15.2.2 取消闹钟  15.2.3 使用多个闹钟  15.2.4 Intent在设置闹钟时的首要职责  15.2.5 闹钟的持久化  15.3 闹钟管理器事实  15.4 参考资料  15.5 小结  第16章 2D动画揭秘  16.1 逐帧动画  16.1.1 计划逐帧动画  16.1.2 创建活动  16.1.3 将动画添加到活动  16.2 布局动画  16.2.1 基本的补间动画类型  16.2.2 计划布局动画测试工具  16.2.3 创建活动和ListView  16.2.4 将ListView制作成动画  16.2.5 使用插值器  16.3 视图动画  16.3.1 理解视图动画  16.3.2 添加动画  16.3.3 使用Camera实现2D图像的深度效果  16.3.4 探索AnimationListener类  16.3.5 关于变换矩阵的一些说明  16.4 资源  16.5 小结  第17章 地图和基于位置的服务  17.1 地图包  17.1.1 从Google获取map-api密钥  17.1.2 MapView和MapActivity  17.1.3 使用覆盖图添加标记  17.2 位置包  17.2.1 使用Android进行地理编码  17.2.2 使用后台线程进行地理编码  17.2.3 LocationManager服务  17.2.4 使用MyLocationOverlay显示位置  17.2.5 使用接近提醒  17.3 参考资料  17.4 小结  第18章 电话API  18.1 使用SMS  18.1.1 发送SMS消息  18.1.2 监视传入的SMS消息  18.1.3 使用SMS文件夹  18.1.4 发送电子邮件  18.2 使用电话管理器  18.3 SIP  18.4 参考资料  18.5 小结  第19章 媒体框架  19.1 使用媒体API  19.2 播放媒体  19.2.1 播放音频内容  19.2.2 播放视频内容  19.3 录制媒体  19.3.1 使用MediaRecorder录制音频  19.3.2 使用AudioRecord录制音频  19.3.3 视频录制  19.3.4 MediaStore类  19.3.5 使用Intnet录制音频  19.3.6 将媒体内容添加到媒体存储  19.3.7 为整个SD卡触发MediaScanner  19.3.8 参考资料  19.4 小结  第20章 使用OpenGL进行3D图形编程  20.1 了解OpenGL的历史和背景  20.1.1 OpenGL ES  20.1.2 OpenGL ES与Java ME  20.1.3 M3G:另一种Java ME 3D图形标准  20.2 OpenGL的基本原理  20.2.1 使用OpenGL ES进行基本绘制  20.2.2 OpenGL照相机和坐标  20.3 在Android使用OpenGL ES  20.3.1 使用GLSurfaceView和相关类  20.3.2 实现Renderer  20.3.3 通过Activity使用GLSurfaceView  20.3.4 更改照相机设置  20.3.5 使用索引添加另一个三角形  20.3.6 为简单的OpenGL三角形制作动画  20.4 OpenGL的运用:形状和纹理  20.4.1 绘制矩形  20.4.2 使用形状  20.4.3 使用纹理  20.4.4 绘制多个图形  20.5 OpenGL ES 2.0  20.5.1 针对OpenGL ES 2.0的Java绑定  20.5.2 呈现步骤  20.5.3 着色器  20.5.4 将着色器编译到程序中  20.5.5 访问着色器程序变量  20.5.6 简单的ES 2.0三角形  20.5.7 关于OpenGL ES 2.0的更多阅读材料  20.6 代码编译说明  20.7 小结  第21章 活动文件夹  21.1 探索活动文件夹  21.1.1 用户如何使用活动文件夹  21.1.2 构建活动文件夹  21.2 代码编译说明  21.3 参考资料  21.4 小结  第22章 主屏幕部件  22.1 主屏幕部件的架构  22.1.1 什么是主屏幕部件  22.1.2 主屏幕部件的用户体验  22.1.3 部件的生命周期  22.2 示例部件应用程序  22.2.1 定义部件提供程序  22.2.2 定义部件尺寸  22.2.3 与部件布局相关的文件  22.2.4 实现部件提供程序  22.2.5 实现部件模型  22.2.6 实现部件配置活动  22.3 部件局限性和扩展  22.4 资源  22.5 小结  第23章 Android搜索  23.1 Android搜索体验  23.1.1 探索Android全局搜索  23.1.2 为全局搜索启用建议提供程序  23.2 活动与搜索键交互  23.2.1 常规活动上的搜索键行为  23.2.2 禁用了搜索的活动的行为  23.2.3 通过菜单显式调用搜索  23.2.4 本地搜索和相关活动  23.2.5 启用键入搜索  23.3 实现简单建议提供程序  23.3.1 计划简单建议提供程序  23.3.2 简单建议提供程序实现文件  23.3.3 实现SimpleSuggestion-Provider类  23.3.4 简单建议提供程序搜索活动  23.3.5 搜索调用方活动  23.3.6 简单建议提供程序用户体验  23.4 实现自定义建议提供程序  23.4.1 计划自定义建议提供程序  23.4.2 SuggestURLProvider项目实现文件  23.4.3 实现SuggestUrlProvider类  23.4.4 实现自定义建议提供程序的搜索活动  23.4.5 自定义建议提供程序描述文件  23.4.6 自定义建议用户体验  23.5 使用操作键和应用程序特有的搜索数据  23.5.1 在Android搜索中使用操作键  23.5.2 使用应用程序特定的搜索上下文  23.6 资源  23.7 对平板电脑的意义  23.8 小结  第24章 文本到语音转换  24.1 Android中的文本到语音转换  24.2 使用语段跟踪语音  24.3 使用音频文件代替话音  24.4 TTS引擎的高级功能  24.4.1 设置音频流  24.4.2 使用耳标  24.4.3 播放静音  24.4.4 选择不同的文本到语音转换引擎  24.4.5 使用语言方法  24.5 参考资料  24.6 小结  第25章 触摸屏  25.1 MotionEvent  25.1.1 MotionEvent 对象  25.1.2 回收MotionEvent  25.1.3 使用VelocityTracker  25.1.4 探索拖放操作  25.2 多点触摸  25.2.1 Android2.2之前的多点触摸  25.2.2 自Android 2.2开始的多点触摸  25.3 触摸地图  25.4 手势  25.4.1 捏合手势  25.4.2 GestureDetector和OnGestureListener  25.4.3 自定义手势  25.4.4 Gestures Builder应用程序  25.5 参考资料  25.6 小结  第26章 传感器  26.1 什么是传感器  26.1.1 检测传感器  26.1.2 可以了解的传感器信息  26.2 获取传感器事件  26.3 解释传感器数据  26.3.1 光线传感器  26.3.2 接近传感器  26.3.3 温度传感器  26.3.4 压力传感器  26.3.5 陀螺仪传感器  26.3.6 加速度计  26.3.7 磁场传感器  26.3.8 结合使用加速度计和磁场传感器  26.3.9 方向传感器  26.3.10 磁偏角和GeomagneticField  26.3.11 重力传感器  26.3.12 直线加速度传感器  26.3.13 旋转矢量传感器  26.3.14 近场通信传感器  26.4 参考资料  26.5 小结  第27章 联系人API  27.1 账户  27.1.1 账户屏幕概览  27.1.2 账户与联系人的相关性  27.1.3 枚举账户  27.2 联系人应用程序  27.2.1 显示联系人  27.2.2 显示联系人详细信息  27.2.3 编辑联系人详细信息  27.2.4 设置联系人的照片  27.2.5 导出联系人  27.2.6 各种联系人数据类型  27.3 联系人  27.3.1 内容SQLite数据库  27.3.2 原始联系人  27.3.3 数据表  27.3.4 聚合联系人  27.3.5 view_contacts  27.3.6 contact_entities_view  27.4 联系人API  27.4.1 浏览账户  27.4.2 浏览聚合联系人  27.4.3 浏览原始联系人  27.4.4 浏览原始联系人数据  27.4.5 添加联系人和它的详细信息  27.5 控制聚合  27.6 同步的影响  27.7 参考资料  27.8 小结  第28章 使用Android Market  28.1 成为发布者  28.1.1 遵守规则  28.1.2 开发人员控制台  28.2 准备销售应用程序  28.2.1 针对不同设备进行测试  28.2.2 支持不同的屏幕尺寸  28.2.3 准备上传AndroidManifest.xml  28.2.4 本地化应用程序  28.2.5 准备应用程序图标  28.2.6 付费应用程序考虑因素  28.2.7 将用户引导至Market  28.2.8 Android授权服务  28.2.9 准备上传.apk文件  28.3 上传应用程序  28.4 Android Market上的用户体验  28.5 更多发布途径  28.6 参考资料  28.7 小结  第29章 多用途的碎片  29.1 什么是碎片  29.1.1 何时使用碎片  29.1.2 碎片的结构  29.1.3 碎片的生命周期  29.1.4 展示生命周期的示例碎片应用程序  29.2 FragmentTransactions和碎片后退栈  29.3 FragmentManager  29.3.1 引用碎片时的注意事项  29.3.2 ListFragments和  29.3.3 在需要时调用独立的活动  29.3.4 碎片的持久化  29.4 对话框碎片  29.4.1 DialogFragment基础知识  29.4.2 DialogFragments示例应用程序  29.5 碎片之间的更多通信方式  29.6 使用ObjectAnimator自定义动画  29.7 参考资料  29.8 小结  第30章 ActionBar  30.1 ActionBar剖析  30.2 选项卡导航操作栏活动  30.2.1 实现基础活动类  30.2.2 为ActionBar分配统一的行为  30.2.3 实现选项卡监听器  30.2.4 实现选项卡操作栏活动  30.2.5 可滚动的调试文本视图布局  30.2.6 操作栏和菜单交互  30.2.7 Android描述文件  30.2.8 测试选项卡操作栏活动  30.3 列表导航操作栏活动  30.3.1 创建SpinnerAdapter  30.3.2 创建列表监听器  30.3.3 设置列表操作栏  30.3.4 更改BaseActionBar-Activity  30.3.5 更改AndroidManifest.xml  30.3.6 测试列表操作栏活动  30.4 标准导航操作栏活动  30.4.1 标准导航操作栏活动  30.4.2 更改BaseActionBar-Activity  30.4.3 更改AndroidManifest.xml  30.4.4 测试标准操作栏活动  30.5 参考资料  30.6 小结  第31章 3.0版中的更多主题  31.1 基于列表的主屏幕部件  31.1.1 3.0版中新的远程视图  31.1.2 在远程视图中使用列表  31.1.3 应用示例:测试主屏幕列表部件  31.1.4 对测试列表部件进行测试  31.2 拖放  31.2.1 3.0版中拖放的基础知识  31.2.2 拖放示例应用程序  31.2.3 测试示例拖放应用程序  31.3 参考资料  31.4 小结 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 144
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值