Fragment BackStack 无法正常工作

Fragment BackStack doesn't work properly

概览

你好,我目前正在尝试开发一个 android 应用程序,其具有新的 material 设计和对 API15 的兼容性。这次我想只使用一个 activity 和多个片段,方法是在 activity 中替换它们。 在这样做的同时,我已经 运行 遇到了多个我已经解决或只是没有再次出现的问题...... 但是,我仍然对 FragmentManager 中的 BackStack 有疑问。工具栏(不是操作栏!)中的后退按钮和后退图标似乎无法正常工作。 我感觉这个问题是由于使用 AppCompatActivity 引起的。 顺便说一句:因为我发现很难理解用一个Activity/多个片段正确编写api22 android应用程序的方法是什么,非常欢迎大家tip/critique!

问题

工具栏中的后退按钮和后退图标不起作用。

当我通过工具栏打开设置时,工具栏中的后退按钮和后退图标都没有让我返回到上一个片段。工具栏中的后退图标什么都不做,(软件)后退按钮关闭应用程序

代码

主要Activity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Load in first fragment
        getFragmentManager().beginTransaction()
                .add(R.id.fragment_container, new MyListFragment())
                .commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            // Replace current fragment with settings fragment
            getFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new SettingsFragment())
                    .addToBackStack(null)
                    .commit();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}

MyListFragment

Just a simple ListFragment

设置片段

public class SettingsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Activate back icon in toolbar
        ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        // Inflate preferences
        addPreferencesFromResource(R.xml.settings);
    }

}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimaryDark"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

value/style.xml(与value-v21/style.xml相同)

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <item name="@color/primary">#2196F3</item>
        <item name="@color/primaryDark">#1976D2</item>
        <item name="@color/accent">#FF4081</item>
    </style>

</resources>

更新

(软件)后退按钮现在在覆盖 onBackPressed() 时可用,如下所示:

public void onBackPressed() {
    getFragmentManager().popBackStack();
}

但是,工具栏中的后退图标仍然无法让我返回。

Toolbar 中 'back' 按钮的问题在于它不是为后退导航设计的。 Toolbar 中的向后箭头用于 'up' 导航(有时令人难以置信的混乱——并且通常与设备 'back' 按钮具有相同的行为)。请参阅此 link 以获得进一步的解释:

http://developer.android.com/design/patterns/navigation.html

虽然肯定有方法可以覆盖 'up' 行为(例如,在 onOptionsItemSelected 方法中覆盖 android.R.id.home),但添加管理设置片段。然后,您可以将 SettingsActivity 的父级 Activity 设置为清单中的 MainActivity。然后 back 和 up 都应该按照你想要的方式工作,而不会覆盖任何标准 OS 行为:

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

希望对您有所帮助!

AppCompatActivity 使用 SupportFragmentManager 而不是 FragmentManager 所以你应该在开始转换时调用 getSupportFragmentManager()

请注意,要使其正常工作,您的片段还需要从支持库中扩展 android.support.v4.app.Fragment,以便返回堆栈按预期工作。

然后就没有必要覆盖 onBackPressed() 方法了。