如何关闭导航控制片段中的导航抽屉layout



我已经创建了 androidx navigation> navigation 模式的项目。现在,我想在Fragment中关闭 drawerLayout onBackPressed()。而且,我也想将OnClickListener设置为抽屉菜单项到我的自定义菜单,我认为在片段中覆盖onBackPressed()

我想知道如何实现这一目标?

这是我的抽屉:

<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:id="@+id/drawerLayoutHome"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="350dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/colorPrimaryDark"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:menu="@menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>

我想实现这一目标:

override fun onBackPressed() {
    if (drawerLayoutHome.isDrawerOpen(GravityCompat.END)) {
        drawerLayoutHome.closeDrawer(GravityCompat.END)
    } else {
        super.onBackPressed()
    }
}

但这是针对Activity,如何在Fragment中实现这一目标?

你好,您可以通过在活动中获取片段并用kotlin代码覆盖on Backpress

来做到这一点。

这是您的背压功能,在此中,您可以获取导航主机,然后您可以检查当前片段或要打开抽屉的片段。

override fun onBackPressed() {
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentHomeHost)
    val completeFragmentList = navHostFragment?.childFragmentManager?.fragments
    if (completeFragmentList != null) {
        when {
            completeFragmentList[0] is HomeFragment -> {
                val home = (completeFragmentList[0] as HomeFragment)

            }
            else -> super.onBackPressed()
        }
    }
    if (drawerLayoutHome.isDrawerOpen(GravityCompat.START)) {
        drawerLayoutHome.closeDrawer(GravityCompat.START)
    } else {
        super.onBackPressed()
    }
}

这是您可以获得选择项目侦听器

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    drawerLayoutHome.closeDrawer(GravityCompat.START)
    return true
}

您可以通过在抽屉活动上实现OnBackStackChangedListenerFragment中执行此操作。
然后,将抽屉与ActionBarDrawerToggle和覆盖onBackStackChanged()链接并同步抽屉切换。

这是完整的片段:

public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener {

    private DrawerLayout drawer;
    private ActionBarDrawerToggle toggle;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Bind listener here
        getSupportFragmentManager().addOnBackStackChangedListener(this);
        drawer = findViewById(R.id.drawer_layout);
        toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        toggle.setToolbarNavigationClickListener(view -> onBackPressed());
        drawer.addDrawerListener(toggle);
        toggle.syncState();
    }

    //Override fragment backstack lister method 
    @Override
    public void onBackStackChanged() {
        //toggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0);
        //getSupportActionBar().setDisplayHomeAsUpEnabled(getSupportFragmentManager().getBackStackEntryCount() > 0);
        toggle.syncState();
    }
    @Override
    public void onBackPressed() {
        drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START))
            drawer.closeDrawer(GravityCompat.START);
        else {
            //super.onBackPressed();
        }
    }
}

我希望这对您有帮助。

简短答案

不可能在Fragment内拦截onBackPressed回调,而无需在托管Activity中添加其他代码。它根本没有在Android SDK中实现。只是停下来。

原始答案

Fragment类中没有onBackPressed回调的东西。但是您可以自己实施:

创建一个接口:

interface FragmentOnBackPressedListener {
  fun onBackPressed()
}

现在在您的活动中:

override fun onBackPressed() {
  // find top fragment
  val currentFragment = supportFragmentManager
    .findFragmentById(R.id.your_nav_host_fragment_id)?.let {
      it.childFragmentManager.fragments.getOrNull(0)
    }
  // check if it implements FragmentOnBackPressedListener 
  if (currentFragment is FragmentOnBackPressedListener ) {
    // if it does, transfer flow to the fragment
    return currentFragment.onBackPressed()
  }
  // if it doesn't, apply default behaviour
  super.onBackPressed()
}

然后在您的片段中:

class ExampleFragment : Fragment(), FragmentOnBackPressedListener {
  override fun onBackPressed() {
    // close your drawer layout here if visible
    // Also: to close fragment, invoke 
    // findNavController().navigateUp() or findNavController().popBackStack()
  }
}

在Kotlin中,只需在您的活动中覆盖此方法,

override fun onBackPressed() {
    if (drawer_layout.isDrawerOpen(GravityCompat.START))
        drawer_layout.closeDrawer(GravityCompat.START)
    else
        super.onBackPressed()
}

您可以用 OnBackPressedDispatcher的片段中控制 onBackPress()

class SampleFragment: Fragment() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true){
            override fun handleOnBackPressed() {
                if (drawer.isDrawerOpen(GravityCompat.START)) {
                    drawer.closeDrawer(GravityCompat.START)
                } else{
                    isEnabled = false
                    requireActivity().onBackPressed() }}
                }
            })
        }
 }

我也有类似的问题。

所以,我在我的活动文件的 onbackpressed 中添加了它。

FragmentManager manager = getSupportFragmentManager();
 if (manager.getBackStackEntryCount() > 0) {
                while (manager.getBackStackEntryCount() > 0) {
                    manager.popBackStackImmediate();
                }

最新更新