【Android UI设计与开发】第12期:顶部标题栏(三)ActionBar实现层级导航的返回效果
转载请注明出处: http://blog.csdn.net/yangyu20121224/article/details/9059459
今天我们继续来讲解ActionBar的使用,不清楚这个类的读者可以翻阅博主前几篇的文章或者在网络上查阅相关
的资料,关于这个类讲解的文章还是很多的,功能确实也很强大。好的,话不多说,让我们赶快进入正题吧。
一、使用应用图标实现层级导航
在默认的情况下,应用程序图标显示在操作栏的左边。你能够把这个图标当做操作项来使用,应用程序可以在这
个图标上响应以下两个操作其中之一:
<1> 返回应用程序的“主”Activity;
<2> 向应用程序上级页面导航。
要实现应用程序图标能够向上导航,首先就要在你的ActionBar中调用SetDisplayHomeAsUpEnabledtrue(true)方法。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); ... }
当用户触摸这个图标时,系统会调用Activity带有android.R.id.home ID的onOptionsItemSelected()方法。在这个响
应中,你既可以启动主Activity,也可以返回你的应用程序结构化层次中用户上一步操作的界面。
如果你要通过应用程序图标的响应来返回主Activity,那么就应该在Itent对象中包括
FLAG_ACTIVITY_CLEAR_TOP标识。用这个标记,如果你要启动的Activity在当前任务中已经存在,那么,堆栈中这
个Activity之上的所有的Activity都有被销毁,并且把这个Activity显示给用户。添加这个标识往往是重要的,因为返回主
Activity相当与一个回退的动作,因此通常不应该再创建一个新的主Activity的实例,否则,最终可能会在当前任务中产
生一个很长的拥有多个主Activity的堆栈。
例如,下例的onOptionsItemSelected()方法实现了返回应用程序的主Activity的操作:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent intent = new Intent(this, HomeActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } }
在用户从另一个应用程序进入当前Activity的情况下,你可能还想要添加FLAG_ACTIVITY_NEW_TASK标识。这
个标识确保在用户返回主页或上级页面时,新的Activity不会被添加到当前的任务中,而是在属于你自己的应用程序的
任务中启动。例如,如果用户通过被另一个应用程序调用的Intent对象启动了你的应用程序中的一个Activity,那么选
择操作栏图标来返回主页或上级页面时,FLAG_ACTIVITY_CLEAR_TOP标识会在属于你的应用程序的任务中启动这
个Activity(不是当前任务)。系统既可以用这个新的Activity做根Activity来启动一个新的任务,也可以把存在后台的拥
有这个Activity实例的一个既存任务带到前台来,并且目标Activity会接受onNewIntent()回调。因此,如果你的Activity
要接收另一个应用程序的Intent对象,那么通常应该给这个Intent对象添加FLAG_ACTIVITY_NEW_TASK标识,如:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // This is called when the Home (Up) button is pressed // in the Action Bar. Intent parentActivityIntent = new Intent(this, MyParentActivity.class); parentActivityIntent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(parentActivityIntent); finish(); return true; } return super.onOptionsItemSelected(item); }
当当前的activity从属于一个不同应用的任务调出时,按下图标按钮应该创建该应用的一个新任务。
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent upIntent = new Intent(this, MyParentActivity.class); if (NavUtils.shouldUpRecreateTask(this, upIntent)) { // This activity is not part of the application's task, so create a new task // with a synthesized back stack. TaskStackBuilder.from(this) .addNextIntent(new Intent(this, MyGreatGrandParentActivity.class)) .addNextIntent(new Intent(this, MyGrandParentActivity.class)) .addNextIntent(upIntent) .startActivities(); finish(); } else { // This activity is part of the application's task, so simply // navigate up to the hierarchical parent activity. NavUtils.navigateUpTo(this, upIntent); } return true; } return super.onOptionsItemSelected(item); }
二、在Fragments中实现层级导航
当在应用中使用fragments时,单一的FragmentTransaction对象能够表示环境的变化,应该被添加到back堆栈。
例如,如果你要实现一个master/detail流程,通过换出fragments,你应该确保在detail界面上点击Back按钮回退到
master界面。
getFragmentManager().beginTransaction().add(detailFragment, "detail") // Add this transaction to the back stack and commit. .addToBackStack() .commit();
如果FragmentTransaction对象在back堆栈上,activity的FragmentManager会处理Back按钮的点击事件。当这一
事件发生时,FragmentManager从back堆栈中弹出最近一次事务,并进行反向的行为。如果你的应用程序更新其他用
户界面元素来反应当前fragment的状态,例如action bar,记得在commit事务的时候更新UI。
getFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } });
三、导航到外部界面
当启动另一个应用程序的activity来允许用户,写一个邮件,或挑选一个照片附件,你一般不会想让用户在Launcher中重新启动程序时回到这个界面。这会对用户造成混淆。为了阻止这种事情的发生,简单的对intent添加FLAG_ACTIVITY_CLEAR_WITH_TASK_RESET标签来启动外部的activity:
Intent externalActivityIntent = new Intent(Intent.ACTION_PICK); externalActivityIntent.setType("image/*"); externalActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(externalActivityIntent);
四、实现的效果图
五、项目结构图
六、详细代码编写
1、这个项目的代码不多,首先是主布局页面,activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/other_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="160dp" android:text="Other_Activity" /> <Button android:id="@+id/external_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/other_btn" android:text="External_Activity" /> </RelativeLayout>
2、然后是另一个界面的布局,activity_other.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> </RelativeLayout>
3、主界面Activity类,MainActivity.java:
package com.yangyu.myactionbar04; import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } /** * 初始化组件 */ private void initView(){ final ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(false); this.findViewById(R.id.other_btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, OtherActivity.class); startActivity(intent); } }); this.findViewById(R.id.external_btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //调用图片浏览器 Intent externalActivityIntent = new Intent(Intent.ACTION_PICK); externalActivityIntent.setType("image/*"); externalActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(externalActivityIntent); } }); } }
4、进入到另一个Activity界面,OtherActivity.java:
package com.yangyu.myactionbar04; import android.app.ActionBar; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NavUtils; import android.support.v4.app.TaskStackBuilder; import android.view.MenuItem; public class OtherActivity extends FragmentActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_other); final ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent upIntent = new Intent(this, MainActivity.class); if (NavUtils.shouldUpRecreateTask(this, upIntent)) { TaskStackBuilder.from(this) //如果这里有很多原始的Activity,它们应该被添加在这里 .addNextIntent(upIntent) .startActivities(); finish(); } else { NavUtils.navigateUpTo(this, upIntent); } return true; } return super.onOptionsItemSelected(item); } }