有关android导航架构组件的问题

时间:2019-05-19 21:24:41

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

我有一个问题。我正在使用android导航架构组件,将底部导航视图与单个活动一起使用。如何使片段只能打开一次?即使导致该片段的按钮被单击了几次? 如何使一个片段仅添加到后台堆栈一次? 我创建了一个测试项目来尝试

xml navigation_test

<?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"
    android:id="@+id/test_nav"
    app:startDestination="@id/firstFragment">
    <fragment
        android:id="@+id/firstFragment"
        android:name="ru.artem_nr.navigation_test.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secondFrag"
            app:destination="@id/navigation"
            app:launchSingleTop="true"
            app:popUpTo="@+id/secondFrag"
            app:popUpToInclusive="false" />
    </fragment>
    <navigation android:id="@+id/navigation"
        app:startDestination="@id/secondFrag">
        <fragment
            android:id="@+id/secondFrag"
            android:name="ru.artem_nr.navigation_test.SecondFrag"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" />
    </navigation>
</navigation>

main_activity

公共类MainActivity扩展了AppCompatActivity        实现NavigationView.OnNavigationItemSelectedListener {

public Toolbar toolbar;
public DrawerLayout drawerLayout;
public NavController navController;
public NavigationView navigationView;

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

    setupNavigation();
}

private void setupNavigation() {

    toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setDisplayShowHomeEnabled(true);

    drawerLayout = findViewById(R.id.drawer_layout);
    navigationView = findViewById(R.id.nav_view);
    navController = Navigation.findNavController(this, R.id.garden_nav_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);
    NavigationUI.setupWithNavController(navigationView, navController);
    navigationView.setNavigationItemSelectedListener((NavigationView.OnNavigationItemSelectedListener) this);
}

@Override
public boolean onSupportNavigateUp() {
    return (boolean) NavigationUI.navigateUp(navController, drawerLayout);
}

@Override
public void onBackPressed() {
    if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
        drawerLayout.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
    menuItem.setChecked(true);

    drawerLayout.closeDrawers();

    int id = menuItem.getItemId();

    switch (id) {
        case R.id.nav_home:
            navController.navigate(R.id.navigation);
            break;
    }
    return true;
}

}

片段-一片空白

2 个答案:

答案 0 :(得分:0)

您需要将片段声明为“ SingleTop”。

导航图编辑器视图右侧的菜单上有一个选项可以做到这一点,位于动画选项下方。

或者,您可以使用setLaunchSingleTop(true)方法通过NavOptions.Builder类以编程方式进行设置,如以下链接中所述:

https://developer.android.com/reference/kotlin/androidx/navigation/NavOptions.Builder#setLaunchSingleTop(kotlin.Boolean)

因此您的on select方法应类似于:

public boolean onNavigationItemSelected(@NonNull MenuItem menuItem){
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true);

NavOptions options = builder.build();
navController.navigate(item.getItemId(), null, options);

答案 1 :(得分:0)

根据this issueBottomNavigationView提供的OnNavigationItemReselectedListener优先于OnNavigationItemSelectedListener设置的NavigationUI

bottomNavigationView.setOnNavigationItemReselectedListener(
    new BottomNavigationView.OnNavigationReselectedListener() {
        @Override
        public void onNavigationItemReselected(MenuItem item) {
            // By doing nothing, we ignore reselection events
        }
    });

NavigationView不提供与this other issue相同的界面,因此您需要copy the default behavior(请注意,它调用NavigationUI.onNavDestinationSelected()而不是仅调用{{ 1}},与您的代码不同),并添加自己的navigate()支票以防止重新选择。