在按下后是什么方法处理导航抽屉的选定状态?
我有一个带有n个条目的导航抽屉(在列表视图中),就像Android Studio中的SDK示例一样。 当我点击导航抽屉条目时,我希望它们被添加到后台堆栈,所以我可以回到它们。
在onNavigationDrawerItemSelected(int pos)中我有
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (position == 0) {
transaction.replace(R.id.container, new FragmentA());
} else if (position == 1) {
transaction.replace(R.id.container, new FragmentB());
} else {
transaction.replace(R.id.container, new FragmentC());
}
transaction.addToBackStack(null);
transaction.commit();
当我点击抽屉中的第二个条目时,B被选中并替换A.如果我之后单击后退按钮,片段A将再次显示,但仍然在导航抽屉中选择了B.
如何在按下后更新抽屉的选择状态?
不知怎的,我需要调用mDrawerListView.setItemChecked(position,true);或NavigationDrawerFragment.selectItem(int position)。但到了哪个位置?我怎么记得呢?
拦截onBackPressed?
@Override
public void onBackPressed() {}
但我怎么知道哪个片段再次活跃?以及它对应的位置。
有一些简单的解决方案我是盲目的看到的吗?似乎将back与导航抽屉结合使用并更新选择状态是标准模式。
答案 0 :(得分:8)
“正确返回导航”文档的Implement Back Navigation for Fragments部分介绍了此模式。
如果您的应用程序更新其他用户界面元素以反映 片段的当前状态,例如操作栏,请记住 提交事务时更新UI。你应该更新 除了何时更改后堆栈后的用户界面 你提交交易。 你可以在什么时候听 通过设置a来恢复
FragmentTransaction
FragmentManager.OnBackStackChangedListener
强>:
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
// Update your UI here.
}
});
这将是刷新导航抽屉中当前选项的适当位置。
答案 1 :(得分:6)
FragmentToActivity
来解决它。
<强>接口强>
public interface FragmentToActivity {
public void SetNavState(int id);
}
<强>片段:强>
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
((FragmentToActivity) getActivity()).SetNavState(R.id.nav_myitemid); //just add this line
}
<强> MainActivity:强>
@Override
public void SetNavState(int id) {
NavigationView nav = (NavigationView) findViewById(R.id.nav_view);
nav.setCheckedItem(id);
}
如果你不知道R.id.nav_myitemid
来自哪里,这是我的 activity_main_drawer.xml :
<?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_myitemid"
android:title="@string/home" />
</group>
</menu>
答案 2 :(得分:5)
我在尝试找出这个问题的解决方案时遇到了很多麻烦,而我最终使用的解决方案并不是很好的&#34;在我看来,但它的确有效。
在我的应用程序中,当我将片段添加到backstack时,我最终在导航抽屉中添加了片段位置。这样我可以使用onBackStackChanged()中的位置调用setItemChecked。基本上我所做的就是这个:
@Override
public void onBackStackChanged() {
FragmentManager fm = getFragmentManager();
String name = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName();
mDrawerList.setItemChecked(Integer.parseInt(name),true);
}
public class DrawerItemClickListener implements android.widget.AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
private void selectItem(int position) {
Fragment fragment;
switch (position) {
case 0: // Home
fragment = new ContentFragment();
break;
case 1: // Another
fragment = new AnotherFragment();
break;
default: // Logout
{
finish();
Intent intent = new Intent(this, StartupActivity.class);
startActivity(intent);
return;
}
}
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(Integer.toString(position))
.commit();
mDrawerList.setItemChecked(position, true);
setTitle(mNavigationItems[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
答案 3 :(得分:3)
以@matiash的优秀答案为基础(如果你给我的答案+1,请务必给他/她+1)
首先,我们假设我们在Activity
getFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
// Update your UI here.
}
});
您可以使用以下内容找到当前片段:
(来自https://stackoverflow.com/a/24589081/878159)
Fragment f = getFragmentManager().findFragmentById(R.id.frag_container);
if (f instanceof CustomFragmentClass) {
// do something with f
f.doSomething();
}
这应该让你更近一步。然后这样的东西会让你引用你的导航抽屉:
nav = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.nav);
然后根据您设置抽屉片段代码的方式:
nav.updateSelected(position);
updateSelected(int)
方法将在您的NavigationDrawerFragment
课程中,可能看起来像这样:
public void updateSelected(int position) {
mCurrentSelectedPosition = position;
if (mDrawerListView != null) {
mDrawerListView.setItemChecked(position, true);
}
}
注意:有很多方法可以做到这一点,但这应该可以让你开始。
答案 4 :(得分:0)
这已经晚了,但是对于那些使用导航菜单而不是列表的人来说,这就是我做的方式
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int position=0;
Fragment fragment;
int id = item.getItemId();
if (id == R.id.nav_home) {
fragment=new HomeFragment();
position=0;
} else if (id == R.id.nav_profile) {
fragment=new ProfileFragment();
position=1;
} else if (id == R.id.nav_settings) {
fragment=new SettingsFragment();
position=2;
}
getSupportFragmentManager()
.beginTransaction()
.add(R.id.relative_container, fragment)
.addToBackStack(""+position)
.commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
并添加backstack的列表器
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
FragmentManager fm = getSupportFragmentManager();
String name = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName();
if(!TextUtils.isEmpty(name))
selectNavigationDrawerItem(Integer.parseInt(name));
}
});
selectNavigationDrawerItem方法
private void selectNavigationDrawerItem(int position){
if(position==0){
navigationView.setCheckedItem(R.id.nav_home);
}
else if(position==1){
navigationView.setCheckedItem(R.id.nav_profile);
}
else if(position==2){
navigationView.setCheckedItem(R.id.nav_settings);
}
}
答案 5 :(得分:0)
这是Kotlin的解决方案。
在要被抽屉选中并突出显示的片段中,只需执行以下操作:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navView: NavigationView = activity!!.findViewById(R.id.nav_view)
navView.setCheckedItem(R.id.name_of_this_fragment)
...
}
答案 6 :(得分:0)
其实很简单。您已经拥有 Drawer
布局中的导航视图。对于按下的每个项目,它会打开相应的片段,对吗?
现在转到每个片段的 onCreateView
并执行此操作...
NavigationView navigationView = getActivity().findViewById(R.id.navigation_view);
navigationView.setCheckedItem(R.id.this_fragment's_item);
此外,在您处理项目点击的主活动中,使用 if 语句,以便
if (navigation_view.getMenu().findItem(R.id.account_nav).isChecked())
drawer_layout.closeDrawer(GravityCompat.START);
以上避免了在自身之上创建片段的多个实例。