Android导航架构组件-导航抽屉图标

时间:2018-07-25 23:08:38

标签: android navigation-drawer android-jetpack android-architecture-navigation android-components

我目前正在使用Android体系结构组件的cURL,但是我的Navigation遇到了问题。它在我的出发地时显示汉堡菜单,但其他Navigation Drawer在显示向上箭头。我相信我的Fragments设置不正确。

在这里您可以看到我的导航抽屉,其中显示2个项,即“主页”和“设置”。在这些片段中的任何一个片段中,您都应该看到“汉堡包”图标。

nav drawer

但是,当导航到“设置片段”时,它会显示“向上”箭头。

toolbar

navigation.graph.xml

navigation_graph

我觉得<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/nav_home"> <!-- Start at HomeFragment --> <fragment android:id="@+id/nav_home" android:name=".HomeFragment" android:label="@string/home"> <!-- Navigate to the Search --> <action android:id="@+id/action_nav_home_to_nav_search" app:destination="@id/nav_search" /> </fragment> <fragment android:id="@+id/nav_settings" android:name=".SettingsFragment" android:label="@string/settings"> <!-- Navigate to the Search --> <action android:id="@+id/action_nav_settings_to_nav_search" app:destination="@id/nav_search" /> </fragment> <fragment android:id="@+id/nav_search" android:name=".SearchFragment" android:label="@string/search" /> </navigation> HomeFragment应该以某种方式联系在一起,但我不确定如何定义。

main_drawer.xml

SettingsFragment

MainActivity

然后在<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@id/nav_home" android:icon="@drawable/ic_home_white_24dp" android:title="@string/home" /> <item android:id="@id/nav_settings" android:icon="@drawable/ic_settings_white_24dp" android:title="@string/settings" /> </group> </menu> 中,我像这样设置。我打电话给MainActivity,但是我还必须亲自设置导航抽屉,并处理setupActionBarWithNavController

onNavigationItemSelected

build.gradle

private fun setupNavigation() {
    navController = findNavController(R.id.mainNavigationFragment)
    setupActionBarWithNavController(this, navController, drawer_layout)

    val toggle = ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer_layout.addDrawerListener(toggle)
        toggle.syncState()

    nav_view.setNavigationItemSelectedListener(this)
}

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val current = navController.currentDestination.id
    if (item.itemId != current) {
        navController.navigate(item.itemId)
    }

    drawer_layout.closeDrawers()
    return true
}

谢谢。

7 个答案:

答案 0 :(得分:5)

在较新的alpha(我有1.0.0-alpha07)中,他们增加了在调用topLevelDestinationIds构造函数时定义AppBarConfiguration的可能性。

所以我这样设置NavController

    val navController = findNavController(R.id.nav_host_fragment)
    val config = AppBarConfiguration(
        setOf(
            R.id.fistTopFragment,
            R.id.secondTopFragment,
            ...
        ),
        dr.drawerLayout
    )
    tb.setupWithNavController(navController, config)

dr是MaterialDrawer,当然tb是工具栏。

然后,它的行为就更像Gmail,至少对于ActionBarDrawerToggle而言,后栈仍然保留。由于必须由我自己处理MaterialDrawer中的项目选择,因此,我将使用全局导航操作(包括popTo)减少向后堆栈的操作,以将其包含到导航图的根片段中,并暂时使用“欢迎屏幕”之类的内容。

另一种解决方法是自定义处理onBackPressed。 您必须首先从活动布局中的主机片段中删除app:defaultNavHost="true"。像这样

override fun onBackPressed() {
    val navController = findNavController(R.id.nav_host_fragment)
    if (navController.currentDestination == null
        || navController.currentDestination!!.id in setOf(
            R.id.fistTopFragment,
            R.id.secondTopFragment,
            ...
        )
    ) {
        super.onBackPressed()
    } else {
        navController.navigateUp()
    }
}

对不起代码,我还在学习Kotlin,所以可能有更好的方法。

答案 1 :(得分:3)

恐怕它是feature of navigation component

  

当您位于非根目录目标位置时,操作栏还将显示“向上”按钮,而在根目录目标位置时,抽屉图标也会显示抽屉图标,从而自动在它们之间进行动画处理。

如果需要,可以尝试使用setupWithNavController(NavigationView, NavController)并自己处理工具栏。

答案 2 :(得分:1)

出现在与BottomNavigationView关联的选项卡片段上的向后箭头是预期的行为。但是,即使在著名的应用程序(Instagram,Youtube中带有底部标签)中,也没有看到它被“按原样”使用。例如,如果您导航到Youtube应用程序中的其他底部选项卡,然后单击设备后退选项,您会注意到它转到上一个选项卡片段,而不退出应用程序。因此,bottomnavigationview选项卡片段不是此处的根目标。

想提醒您前进时可能遇到的其他重要问题:

不过,您可以使用多个挂钩自定义行为:

  1. onBackPressed-如果打开则关闭抽屉布局

    override fun onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
          drawerLayout.closeDrawer(GravityCompat.START)
        } else {
          super.onBackPressed()
        }
     }
    
  2. 添加navController.addOnNavigatedListener(..)并在侦听器内部自定义HomeAsUpIndicator图标

  3. 覆盖onOptionsItemSelected以自定义ID为android.R.id.home操作的菜单

  4. 设置自定义片段导航器以自定义片段的处理方式(替换或显示/隐藏)

    navHostFragment = supportFragmentManager
            .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
    val customNavigator = CustomFragmentNavigator(navHostFragment.requireContext(),
            navHostFragment.childFragmentManager, navHostFragment.id)
    navHostFragment.navController.navigatorProvider.addNavigator(customNavigator)
    
    val inflater = navHostFragment.navController.navInflater
    val graph = inflater.inflate(R.navigation.main_nav_graph)
    navHostFragment.navController.graph = graph
    

请记住导航拱形组件仍处于alpha状态,因此请明智地使用它。

答案 3 :(得分:1)

如果需要,可以使用NavController.OnNavigatedListener并使用以下代码设置标题。

@Override
public void onNavigated(@NonNull NavController controller, @NonNull NavDestination destination) {
    mActivityBinding.toolbar.setTitle(destination.getLabel());
}

记住要在导航图中设置标签。

答案 4 :(得分:1)

我为这个问题做了一个简单的例子。解决方案与全能者的答案几乎相同。 https://github.com/isaul32/android-sunflower

首先创建一组顶级目的地

package main

import (
    "fmt"
    "math/rand"
    "time"
)

type list []string

func main() {

    s := list{
        "Tanki",
        "Left 4 Dead",
        "Rocket League",
        "Call Of Duty : AW",
    }
    s.shuffle()
    s.print()
}

func (l list) print() {
    for i, v := range l {
        fmt.Println(i, v)
    }
}

func (l list) shuffle() list {
    src := rand.NewSource(time.Now().UnixNano())
    r := rand.New(src)
    for i := range l {
        n := r.Intn(len(l) - 1)
        l[i], l[n] = l[n], l[i]
    }
    return l
}

然后像这样覆盖onSupportNavigateUp函数

val topLevelDestinations = setOf(R.id.garden_fragment,
        R.id.plant_list_fragment)
appBarConfiguration = AppBarConfiguration.Builder(topLevelDestinations)
        .setDrawerLayout(drawerLayout)
        .build()

答案 5 :(得分:0)

我认为您的菜单项应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
            android:id="@id/nav_home"
            android:icon="@drawable/ic_home_white_24dp"
            android:title="@string/home" />

        <item
            android:id="@id/nav_settings"
            android:icon="@drawable/ic_settings_white_24dp"
            android:title="@string/settings" />

</menu>

希望这会有所帮助

编码愉快...

答案 6 :(得分:0)

我完全同意这里的观点,但这是图书馆的一部分

  

setupActionBarWithNavController

     

设置由AppCompatActivity.getSupportActionBar()返回的ActionBar以与NavController一起使用。

     

通过调用此方法,操作栏上的标题将在目的地更改时自动更新(假设有有效标签)。

     

导航图的起始目的地被认为是唯一的顶级目的地。如果给定的DrawerLayout不为null,则在导航图的开始目标上,ActionBar将显示抽屉图标。在所有其他目标上,ActionBar将显示“向上”按钮。调用navigationUp(NavController,DrawerLayout)处理“上移”按钮。

这对我来说是坏的,而不是预期的结果,所以我在做的仍然是在使用

的导航视图中使用它
    navController = Navigation.findNavController(this, R.id.nav_host);
    NavigationUI.setupWithNavController(navigationView,navController);

然后让听众更新标题以及我想要更改的其他任何内容

   navController.addOnNavigatedListener((controller, destination) -> {
        setToolbarColour(R.color.primary);
        switch (destination.getId()){
            case R.id.dashBoard :
                setToolbarColour(android.R.color.transparent);
                break;
            case R.id.requests :
                toolbar.setTitle(getString(R.string.request));
                break;

        }
    });

然后我为这些片段中的每个片段创建一个新的导航图,虽然不太好,但是我得到了预期的结果