使用 Android BottomNavigation 保存片段状态
Saving Fragment state with Android BottomNavigation
我是Android开发的新手,所以我不明白很多,也许是基本的东西,也许甚至陈述的主题也没有完全反映我的问题,我提前道歉,我无法制定更多恰恰。请帮我解答一些问题。
我的应用程序中有一个包含三个菜单项的 BottomNavigation。喜欢图片:
bottom nav
最初,我按照标准 Android Studio 示例进行操作:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
}
}
在这段代码中,菜单项切换片段,保存每个片段的状态(我不知道具体如何,它似乎在导航控制器内部的某个地方)。
但现在我需要中间按钮来执行不同的功能,即不参与切换片段。
唯一合适的方法是使用 setOnItemSelectedListener。
那么我的代码将如下所示:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
navView.setOnItemSelectedListener(
new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
navController.navigate(R.id.navigation_home);
break;
case R.id.navigation_update:
// work for middle menu item
break;
case R.id.navigation_notifications:
navController.navigate(R.id.navigation_notifications, savedInstanceState);
break;
}
return true;
}
});
}
}
它甚至可以工作,只是片段不再保存它们的状态。也就是说,例如,在第一个片段中我有一个 RecyclerView,如果我向下滚动它,切换到另一个片段,然后 return 返回,那么 RecyclerView 处于默认状态(未滚动),即状态尚未保存。
事实证明,在第一个版本的代码中,我不能对中间的菜单项进行单独的操作,而在第二个版本中,片段的状态没有被保存。
提示正确处理该问题的方法。这样可以给中间的菜单项分配一个单独的作业,并且可以保存片段的状态。
您可以使用 navController.addOnDestinationChangedListener 而不是使用 navView.setOnItemClickListener,并且在重写的 onDestinationChanged 方法中,您可以检查
if(destination.id == R.id.navigation_update) {
//your custom action here
}
我能够使用导航使用标准工具解决问题。
我刚找到一个菜单项并向其添加了一个 OnClickListener。
BottomNavigationItemView updateBtn = findViewById(R.id.navigation_update);
updateBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// todo
}
});
因此,切换片段和单击中间菜单项都可以正常工作。
我是Android开发的新手,所以我不明白很多,也许是基本的东西,也许甚至陈述的主题也没有完全反映我的问题,我提前道歉,我无法制定更多恰恰。请帮我解答一些问题。
我的应用程序中有一个包含三个菜单项的 BottomNavigation。喜欢图片:
bottom nav
最初,我按照标准 Android Studio 示例进行操作:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
}
}
在这段代码中,菜单项切换片段,保存每个片段的状态(我不知道具体如何,它似乎在导航控制器内部的某个地方)。
但现在我需要中间按钮来执行不同的功能,即不参与切换片段。
唯一合适的方法是使用 setOnItemSelectedListener。
那么我的代码将如下所示:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
navView.setOnItemSelectedListener(
new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
navController.navigate(R.id.navigation_home);
break;
case R.id.navigation_update:
// work for middle menu item
break;
case R.id.navigation_notifications:
navController.navigate(R.id.navigation_notifications, savedInstanceState);
break;
}
return true;
}
});
}
}
它甚至可以工作,只是片段不再保存它们的状态。也就是说,例如,在第一个片段中我有一个 RecyclerView,如果我向下滚动它,切换到另一个片段,然后 return 返回,那么 RecyclerView 处于默认状态(未滚动),即状态尚未保存。
事实证明,在第一个版本的代码中,我不能对中间的菜单项进行单独的操作,而在第二个版本中,片段的状态没有被保存。
提示正确处理该问题的方法。这样可以给中间的菜单项分配一个单独的作业,并且可以保存片段的状态。
您可以使用 navController.addOnDestinationChangedListener 而不是使用 navView.setOnItemClickListener,并且在重写的 onDestinationChanged 方法中,您可以检查
if(destination.id == R.id.navigation_update) {
//your custom action here
}
我能够使用导航使用标准工具解决问题。 我刚找到一个菜单项并向其添加了一个 OnClickListener。
BottomNavigationItemView updateBtn = findViewById(R.id.navigation_update);
updateBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// todo
}
});
因此,切换片段和单击中间菜单项都可以正常工作。