如何在导航控件片段中关闭导航DrawerLayout onBackPressed

时间:2019-04-30 20:06:53

标签: android kotlin navigation navigation-drawer

我用 Navigation 模式创建了一个 Androidx 项目。现在,我要关闭片段中的 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中实现?

6 个答案:

答案 0 :(得分:8)

您好,您可以通过激活片段并使用Kotlin代码覆盖onbackpress来实现它

这是您的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
}

答案 1 :(得分:4)

您可以在抽屉活动中实施Fragment,从而在OnBackStackChangedListener内完成此操作。
然后,将抽屉与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();
        }
    }
}

我希望这会对您有所帮助。

答案 2 :(得分:2)

简短答案

如果不在托管onBackPressed内添加其他代码,则无法拦截Fragment内的Activity回调。根本没有在Android SDK中实现它。停下来。

原始答案

onBackPressed类中没有诸如Fragment回调的事情。但是您可以自己实现它:

创建界面:

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()
  }

}

答案 3 :(得分:0)

我遇到了类似的问题。

因此,我将其添加到我的活动文件的 onBackPressed 中。

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

答案 4 :(得分:0)

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

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() }}
                }
            })
        }
 }

答案 5 :(得分:-1)

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

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