【问题标题】:Navigation similar to Gmail Android application导航类似于 Gmail Android 应用程序
【发布时间】:2017-01-18 17:17:19
【问题描述】:

注意:我正在使用 Xamarin - 但会接受 Java Android 中的答案 -

我有一个 android 应用程序,其中的导航与 gmail android 应用程序类似。

我有一个左抽屉导航。有以下选项

  1. 资产(如 gmail 应用程序收件箱片段)-

当用户启动应用程序时,默认情况下会显示此片段 - 当用户在此 Activity 上并按下后退按钮时,应用程序应关闭

  1. 地理围栏

当用户在这个片段上并按下它应该返回到资产(收件箱)片段

  1. 通知

当用户在这个片段上并按下它应该返回到资产(收件箱)片段

这就是我在 Activity 中启动默认片段的方式

protected override void OnCreate(Bundle savedInstanceState)
{
 // Set the initial fragment i.e. AssetListFragment
 var fragment = new AssetListFragment();
 var ft = SupportFragmentManager.BeginTransaction()
                        .Replace(Resource.Id.content_frame, fragment);

  ft.Commit();

}

然后当点击抽屉导航中的一个项目时,我会启动片段,如下所示:

    private void NavigationDrawerItemSelected(object sender, NavigationView.NavigationItemSelectedEventArgs e)
    {
        Android.Support.V4.App.Fragment fragment = null;

        switch (e.MenuItem.ItemId)
        {
            case Resource.Id.nav_assets:
                fragment = new AssetListFragment();
                break;

            case Resource.Id.nav_geofences:
                fragment = new GeofenceFragment();
                break;

            case Resource.Id.nav_notifications:
                fragment = new NotificationsFragment();
                break;
        }


        if (fragment != null)
        {
            var fragmentName = fragment.GetType().Name;

            var fragmentPopped = SupportFragmentManager.PopBackStackImmediate(fragmentName, 0);

            if (!fragmentPopped)
            {
                var ft = SupportFragmentManager
                                .BeginTransaction()
                                .AddToBackStack(fragmentName)
                                .Replace(Resource.Id.content_frame, fragment);

                ft.Commit();
            }
        }

        // Close drawer
        _drawerLayout.CloseDrawers();
    }

当用户点击后退按钮时,我做了以下操作:

    public override void OnBackPressed()
    {
        if (_drawerLayout != null && _drawerLayout.IsDrawerOpen(GravityCompat.Start))
            _drawerLayout.CloseDrawers();
        else
        {
            if (SupportFragmentManager.BackStackEntryCount > 0)
                SupportFragmentManager.PopBackStackImmediate();
            else
                base.OnBackPressed();

        }

    }

我需要做的是总是回到第一个屏幕(在我的情况下是 AssetListFragment)(在 gmail android 应用程序中是收件箱片段)

我该怎么做?目前从 Navigation Draw 加载的所有片段都已添加到堆栈中,当我单击“后退”按钮时,它会转到上一个片段而不是第一个片段。

【问题讨论】:

    标签: android android-fragments xamarin xamarin.android


    【解决方案1】:

    您将片段添加到堆栈中,当您在第二个或第三个片段并按下返回按钮时,您应该在AssetListFragment之前弹出所有片段

    Android 提供 API PopBackStackImmediate(id,flag) 来导航目标片段。

    在我的示例中,FragmentOne 是第一个片段,例如 AssetListFragment

    if (FragmentManager.BackStackEntryCount > 0)
    {
        FragmentManager.PopBackStackImmediate(new FragmentOne().Id, PopBackStackFlags.None);
    }
    else
    {
        base.OnBackPressed();
    }
    

    编辑

    根据您在堆栈中的要求,片段应存储为 1->2->3->1,当我们发现当前片段为 1 并单击返回按钮时应关闭应用程序:

    Android没有提供检测当前fragment的API,我们可以添加一个静态Arraylist来存储你添加的fragment。

    public static ArrayList myFragments = new ArrayList();

    将您替换的每个片段添加到列表中:

     private void Bt1_Click(object sender, EventArgs e)
            {
                FragmentThree fThree = new FragmentThree();
                FragmentManager fm = FragmentManager;
                FragmentTransaction tx = fm.BeginTransaction();
                //tx.Hide(this);
                //tx.Add(Resource.Id.frameLayout1, fThree, "THREE");
                MainActivity.myFragments.Add(fThree);
                tx.Replace(Resource.Id.frameLayout1, fThree, "THREE");  
                tx.AddToBackStack(null);
                tx.Commit();
            }
    

    检查当前片段是否是 FragmentOne :

    Fragment lastFragment = (Fragment)(myFragments[myFragments.Count - 1]);
    
    
                if (lastFragment.Tag.Equals("ONE"))
                {
                    myFragments.Clear();
                    Finish();
    
                }
                else
                {
                    if (FragmentManager.BackStackEntryCount > 0)
                    {
    
                        FragmentManager.PopBackStackImmediate(new FragmentOne().Id, PopBackStackFlags.None);
                        myFragments.RemoveRange(1, myFragments.Count-1);
                    }
    
                    else
                    {
                        base.OnBackPressed();
                    }
                }
    

    作为另一种解决方法,当您按下返回按钮时,只需将当前片段替换为 AssetListFragment

       public override void OnBackPressed()
        {
            if (_drawerLayout != null && _drawerLayout.IsDrawerOpen(GravityCompat.Start))
                _drawerLayout.CloseDrawers();
            else if(FragmentManager.BackStackEntryCount > 1)
            {
                Fragment fragment = new AssetListFragment();
                var ft = SupportFragmentManager
                            .BeginTransaction()
                            .AddToBackStack(null)
                            .Replace(Resource.Id.content_frame, fragment);
                ft.Commit();
            }
            else
            {
                 base.OnBackPressed();
            }
        }
    

    【讨论】:

    • 如果我们从 Fragment 1 -> 2 -> 3 -> 1 通过导航抽屉(不要单击返回),那么当在 Fragment 1 上单击返回按钮时,这将使应用程序保持打开状态- 但如果用户在片段 1 上 - 它应该始终关闭应用程序
    • @DawoodAwan "but if a user is on fragment 1" 我不明白这句话,用户应该在片段 1 上并单击后退按钮保持应用程序打开。你可以试试我刚才编辑的代码。如果第一个片段在那里,我认为你可以回到 1。如果没有,我认为你可以回到 2。
    • 如果用户在片段 1 上,它应该总是关闭应用程序 - 如果用户在 2 或 3 上,它应该总是回到 1
    猜你喜欢
    • 2011-04-07
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多