如何实现Android ActionBar的返回按钮?

149

我有一个带有ListView的Activity。当用户点击项目时,该项目的“查看器”会打开:

List1.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {

        Intent nextScreen = new Intent(context,ServicesViewActivity.class);
        String[] Service = (String[])List1.getItemAtPosition(arg2);

        //Sending data to another Activity
        nextScreen.putExtra("data", datainfo);
        startActivityForResult(nextScreen,0);
        overridePendingTransition(R.anim.right_enter, R.anim.left_exit);
    }
});

这个代码可以正常工作,但是在操作栏上,应用图标旁边的返回箭头无法激活。我是否遗漏了什么?


66
在ServicesViewActivity中,在onCreate方法中可以看到getActionBar().setDisplayHomeAsUpEnabled(true);语句,而在onOptionsItemSelected方法中,当选择的菜单项为android.R.id.home时,会调用onBackPressed()方法。 - Selvin
8
为什么不考虑将其放到书架上作为答案呢? - KarlKarlsom
14个回答

283

Selvin已经发布了正确的答案。这里是漂亮代码的解决方案:

public class ServicesViewActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // etc...
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
}

NavUtils.navigateUpFromSameTask(this) 函数需要在 AndroidManifest.xml 文件中定义父活动

<activity android:name="com.example.ServicesViewActivity" >
    <meta-data
     android:name="android.support.PARENT_ACTIVITY"
     android:value="com.example.ParentActivity" />
</activity>

请参阅此处以获取更多信息。


1
在我的情况下,我正在寻找一种方法,以便在返回到父级时不调用其onCreate方法。为了做到这一点,我使用了您的实现,但是我调用了finish(),而不是NavUtils.navigateUpFromSameTask(this)。 finish() 调用了我的onStart而不是onCreate,这对我来说更理想。 - Jon
在清单文件中设置元数据是使导航按钮正常工作的关键。 - VSB
如果你正在使用支持库,可以使用getActionBar().setDisplayHomeAsUpEnabled(true); - Abhinav Upadhyay
你如何改变“擦除”的方向?默认情况下,实现此后退导航会将屏幕从右向左扫过去,并且看起来像是正在加载新的屏幕。然而,我希望它能够从左向右擦过去,就像按设备自带的返回键一样。 - stingray_
1
我收到了错误信息:Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference。 - Jones
onSupportNavigateUp()中使用getSupportActionBar().setDisplayHomeAsUpEnabled(true);onBackPressed() - Ganesh MB

187

请确保在Activity中启用了ActionBar的Home按钮:

Android,API 5+:

@Override
public void onBackPressed() {
     ...
     super.onBackPressed();
}

ActionBarSherlock和App-Compat,API 7+:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

Android, API 11+:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

扩展ActionBarActivityMainActivity示例:

public class MainActivity extends ActionBarActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Back button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home: 
            // API 5+ solution
            onBackPressed();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }
}

通过这种方式,您可以使所有需要后退按钮的活动都具备后退功能。

Android, API 16+:

http://developer.android.com/training/implementing-navigation/ancestral.html

AndroidManifest.xml:

<application ... >
    ...
    <!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" >
        <!-- The meta-data element is needed for versions lower than 4.1 -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>

一个扩展ActionBarActivityMainActivity示例:

public class MainActivity extends ActionBarActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Back button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

当我将 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 更改为 getActionBar().setDisplayHomeAsUpEnabled(true); 并在 onCreate 方法内外添加这些 @SuppressLint("NewApi") 时,它对我有效。参考链接:=> http://developer.android.com/training/implementing-navigation/ancestral.html - gnganapath
1
@ ganpath 小心,使用 getActionBar 是针对 API 11+ 的。 - Jared Burrows

23
为了启用ActionBar返回按钮,你需要在Activity中使用ActionBar。这可以由你正在使用的主题来设置。你可以在AndroidManifest.xml中为你的Activity设置主题。如果你使用的是@android:style/Theme.NoTitleBar这样的主题,那么你就没有ActionBar。在这种情况下,调用getActionBar()会返回null。所以请先确保你有一个ActionBar。
接下来的步骤是在AndroidManifest.xml中将android:parentActivityName设置为你想要导航到的Activity名称,当你按下返回按钮时会导航到该Activity。
现在你可以在“子” Activity 的onCreate方法中启用返回按钮。
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

现在您应该实现后退按钮的逻辑。您只需在“child”活动中覆盖onOptionsItemSelected方法,并检查后退按钮的ID,即android.R.id.home

现在,您可以触发NavUtils.navigateUpFromSameTask(this);方法但是,如果您没有在AndroidManifest.xml中指定android:parentActivityName,这将导致应用程序崩溃。

有时这正是您想要的,因为它会提醒您忘记了“某些事情”。因此,如果您想要防止这种情况,请使用getParentActivityIntent()方法检查您的活动是否有父级。如果返回null,则未指定父项。

在这种情况下,您可以触发onBackPressed()方法,它基本上与用户按设备上的后退按钮相同。一个很好的实现,永远不会使您的应用程序崩溃,如下所示:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            if (getParentActivityIntent() == null) {
                Log.i(TAG, "You have forgotten to specify the parentActivityName in the AndroidManifest!");
                onBackPressed();
            } else {
                NavUtils.navigateUpFromSameTask(this);
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
请注意,用户看到的动画在 NavUtils.navigateUpFromSameTask(this);onBackPressed() 之间是不同的。 选择哪条路取决于您,但我发现这个解决方案很有帮助,特别是如果您为所有活动使用基类。

20

OnCreate方法中添加以下内容:

if (getSupportActionBar() != null) {
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

然后添加这个方法:

@Override
public boolean onSupportNavigateUp() {
    onBackPressed();
    return true;
}

11

AndroidManifest 文件:

    <activity android:name=".activity.DetailsActivity">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="br.com.halyson.materialdesign.activity.HomeActivity" />
    </activity>

在DetailsActivity中添加:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);   
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

它工作了:]


1
似乎这是我最简单的方式。谢谢。 - TuanDPH

7

Android Annotations:

@OptionsItem(android.R.id.home)
void homeSelected() {
    onBackPressed();
}

来源:https://github.com/excilys/androidannotations

AndroidAnnotations是一个开源框架,它可以帮助您更轻松地编写Android应用程序。使用注释,您可以自动生成样板代码,并且可以更快地开发应用程序。此外,该框架提供了许多有用的功能,例如依赖注入、视图绑定和线程处理。

6

我认为onSupportNavigateUp()是最简单和最好的方法

可以在下面的stackoverflow答案中查看完整解决方案。链接:点此查看完整代码


1
太好了!对我有用。谢谢! - morja

3

https://dev59.com/SmUo5IYBdhLWcg3w5Syl#46903870

为了实现这个目标,只需两步操作:
第一步:转到AndroidManifest.xml文件,在标签中添加参数android:parentActivityName=".home.HomeActivity"。
例如:
 <activity
    android:name=".home.ActivityDetail"
    android:parentActivityName=".home.HomeActivity"
    android:screenOrientation="portrait" />

步骤2:在ActivityDetail中添加您的上一页/活动的操作

示例:

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

1

以下步骤足以实现返回按钮:

步骤1: 此代码应位于Manifest.xml文件中

<activity android:name=".activity.ChildActivity"
        android:parentActivityName=".activity.ParentActivity"
        android:screenOrientation="portrait">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".activity.ParentActivity" /></activity>

步骤2: 您不会提供

finish();

在启动子活动时,在您的父活动中使用。
步骤3: 如果您需要从子活动返回到父活动,则只需为子活动提供此代码。
startActivity(new Intent(ParentActivity.this, ChildActivity.class));

1
如果您正在使用工具栏,我曾经遇到过同样的问题。我通过以下两个步骤解决了这个问题:
  1. 在AndroidManifest.xml中
<activity android:name=".activity.SecondActivity" android:parentActivityName=".activity.MainActivity"/>

在SecondActivity中,添加以下内容...
Toolbar toolbar = findViewById(R.id.second_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接