【问题标题】:Up navigation in `AppCompatActivity` with `Fragments`使用“片段”在“AppCompatActivity”中向上导航
【发布时间】:2015-09-02 13:24:30
【问题描述】:

我正在尝试在我的应用程序中设置正确的导航,它替换了主要内容区域中的Fragments,所以我只有一个Activity。我有一个主要的Fragment 和几个子Fragments,例如一个Fragment 用于偏好。使用后退按钮时一切正常,但我想实现包括图标在内的向上导航。我正在使用通过Activity.getSupportActionBar() 获取的ActionBar 以及来自appcompat 的ToolbarActionBarDrawerToggle

一开始我在设置Drawer 时关注了this tutorial

当前行为: 当我启动应用程序时,列表/抽屉图标显示在ActionBar 的左侧。当我单击它时,Drawer 打开,我可以选择项目。子Fragments 被替换到我的内容中,后退按钮弹出堆栈,带我回到之前的Fragment

缺失行为: 左上角的列表/抽屉图标永远不会被后退箭头图标取代,我无法弄清楚如何正确实现这一点。在单击列表/抽屉图标时,Drawer总是被拉出,无论我在哪个Fragment

我尝试了什么:

  1. 我尝试关注this 的回答。它有点工作,这意味着后退箭头图标设置在子Fragments 中,但单击后退箭头仍会打开Drawer,而不是提供向上导航。此外,当使用后退按钮“向上”时,列表/抽屉图标被替换为空。
  2. 我也尝试关注this 的回答。在这里,所需的ActionBar 行为/外观在各种Fragments 的onCreate() 方法中实现。使用这个我可以让后退箭头向上,但单击箭头时仍然会拉动Drawer
  3. 其他各种小事和小技巧。

我的问题:

  1. 下面的代码有什么问题?
  2. 使用ActionBarToolbarActionBarDrawerToggle 的组合来实现Drawer 导航和向上导航是否正确/正常?

MyActivity.onCreate():

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // Other stuff

    // Setup drawer.
    mDrawerFragment = (DrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.mm_navigation_drawer);
    mDrawerFragment.initialize(this, (DrawerLayout)findViewById(R.id.mm_drawer_layout), toolbar);
}

DrawerFragment 类

public class DrawerFragment extends Fragment
{
    private MyActivity                      mMyActivity;
    private MyActionBarDrawerToggle         mMyBarDrawerToggle;
    private DrawerLayout                    mDrawerLayout;
    private FragmentDrawerListener          mFragmentDrawerListener;
    private View                            mContainerView;

    public void initialize(MyActivity myActivity, final DrawerLayout drawerLayout, final Toolbar toolbar)
    {
        mMyActivity = myActivity;
        mFragmentDrawerListener = mMyActivity;
        mContainerView = myActivity.findViewById(R.id.mm_navigation_drawer);

        mMyActionBarDrawerToggle = new MyActionBarDrawerToggle(myActivity, drawerLayout, toolbar, R.string.mm_drawer_open, R.string.mm_drawer_close);

        mDrawerLayout = drawerLayout;
        mDrawerLayout.setDrawerListener(mMyActionBarDrawerToggle);
        mDrawerLayout.post(new Runnable()
        {
            @Override
            public void run()
            {
                mMyActionBarDrawerToggle.syncState();
            }
        });
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState)
    {
        // Not relevant, just create and return the View.
    }
}

MyActivity.onDrawerItemSelected()

接口FragmentDrawerListener的实现在MyActivity类中完成。它只是将内容区域替换为其他Fragments,使用FragmentTransactions。

@Override
public void onDrawerItemSelected(View view, int postion)
{
    switch (postion)
    {
        case DrawerAdapter.ITEM_FILTERED_RECIPES:
            showFilteredRecipesFragment();
            break;

        case DrawerAdapter.ITEM_SELECTED_RECIPES:
            showSelectedRecipesFragment();
            break;

        case DrawerAdapter.ITEM_SHOPPING_LIST:
            showShoppingListFragment();
            break;

        case DrawerAdapter.ITEM_SETTINGS:
            showSettingsFragment();
            break;

        case DrawerAdapter.ITEM_ABOUT:
            showAboutFragment();
            break;
    }
}

MyActionBarDrawerToggle 类

public class MyActionBarDrawerToggle extends ActionBarDrawerToggle
{
    private MyActivity mMyActivity;
    private Toolbar mToolbar;

    public MyActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes)
    {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
        mMyActivity = (MyActivity) activity;
        mToolbar = toolbar;
    }

    @Override
    public void onDrawerOpened(View drawerView)
    {
        super.onDrawerOpened(drawerView);
        mMyActivity.invalidateOptionsMenu();
    }

    @Override
    public void onDrawerClosed(View drawerView)
    {
        super.onDrawerClosed(drawerView);
        mMyActivity.invalidateOptionsMenu();
    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset)
    {
        super.onDrawerSlide(drawerView, slideOffset);
        mToolbar.setAlpha(1 - slideOffset / 2);
    }
}

DrawerFragment 在主布局中使用简单的静态Fragment 实例进行膨胀,如下所示:

<fragment
    android:id="@+id/my_navigation_drawer"
    android:name="com.my.company.gui.drawer.DrawerFragment"
    android:layout_width="@dimen/my_nav_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:layout="@layout/my_drawer_navigation_fragment"
    tools:layout="@layout/my_drawer_navigation_fragment">
</fragment>

【问题讨论】:

    标签: android android-fragments navigation


    【解决方案1】:

    如果您正在为您的应用程序使用材料设计,那么您应该使用 Toolbar 来替换活动中的 Actionbar。您仍将保留您的ActionBarDrawerToggle,并且功能将保持不变。

    至于您的片段,只要它们被相同的活动“容纳”(即带有抽屉的活动),更改片段不会导致抽屉切换更改后退箭头。只有当您导航到新活动时,它才会改变。只有这样,主要活动才会被视为家,而其他活动则有一个返回箭头来导航

    【讨论】:

    • 那么您的意思是,使用Toolbar 的此类导航旨在使用Activitys 来替换内容,而不是Fragments?
    • 在活动之间使用Toolbar 进行导航。如果你想在同一个 Activity 中的 Fragment 之间实现向后导航,你必须重写 onBackPressed 方法。
    • 好的,所以我可能不得不将一些Fragments 重写为Activitys。这样做的首选方法是在所有 XML 文件中使用相同的 Toolbar,然后在 Activity.onCreate() 中获取它,然后调用 setSupportActionBar(Toolbar)?我想getSupportActionBar().setDisplayHomeAsUpEnabled(true); 也必须被调用?
    • 通过在不同的 xml 文件上创建工具栏来简化事情,然后在您需要它出现的每个活动中使用 &lt;include /&gt; 标记添加它。是的,您需要在每个活动中添加setSupportActionBar(toolbar),并为每个活动添加getSupportActionBar().setDisplayAsHomeUpEnabled(true),以便正确导航。
    • 现在似乎工作正常,除了在我的孩子Activity 中按下向上导航按钮时,onDestroy() 直接在我的主Activity 中调用,然后是onCreate()。这是预期的行为吗?据我从文档中可以看出,此时不应调用onDestroy()。按下后退按钮可提供所需的行为;我刚回到主Activity,状态已恢复。您是否偶然知道这方面的知识?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2015-07-31
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    相关资源
    最近更新 更多