从 Fragment 中的按钮单击打开导航抽屉 (Kotlin)

Sca*_*lli 4 android fragment kotlin navigation-drawer

在 Fragment 中创建了一个自定义按钮我试图单击它时在 Activity 中打开导航抽屉。

当您滑动时,导航抽屉仍然可以正常打开,但是当我单击按钮时应用程序崩溃了。

我想这是因为我试图从 Fragment 访问,但我不知所措..

分段

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    val binding: SiteFragmentBinding = DataBindingUtil.inflate(
        inflater, R.layout.site_fragment, container, false
    )

    binding.apply {
        siteOverflowOptionsMenuButton.setOnClickListener{
            showPopUp(it)
        }

        siteDrawerMenuButton.setOnClickListener{
            drawer_layout.openDrawer(nav_view)  // this crashes (also crashes with Gravity.LEFT or similar)
        }

    }

    return binding.root
}
Run Code Online (Sandbox Code Playgroud)

活动.xml

?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/siteNavHostFragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/site_navigation" />

    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:id="@+id/nav_view"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_menu"

        />

</androidx.drawerlayout.widget.DrawerLayout>
Run Code Online (Sandbox Code Playgroud)

site_fragment.xml

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    val binding: SiteFragmentBinding = DataBindingUtil.inflate(
        inflater, R.layout.site_fragment, container, false
    )

    binding.apply {
        siteOverflowOptionsMenuButton.setOnClickListener{
            showPopUp(it)
        }

        siteDrawerMenuButton.setOnClickListener{
            drawer_layout.openDrawer(nav_view)  // this crashes (also crashes with Gravity.LEFT or similar)
        }

    }

    return binding.root
}
Run Code Online (Sandbox Code Playgroud)

drawer_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_first_fragment"
            android:icon="@drawable/ic_exit"
            android:title="First" />
        <item
            android:id="@+id/nav_second_fragment"
            android:icon="@drawable/ic_priority"
            android:title="Second" />
        <item
            android:id="@+id/nav_third_fragment"
            android:icon="@drawable/ic_filter"
            android:title="Third" />
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_contact"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_location"
                android:title="Send" />
        </menu>

    </item>

    <item android:title="Sub items">
        <menu>
            <group android:checkableBehavior="single">
                <item
                    android:icon="@drawable/ic_star_full"
                    android:title="Sub item 1" />
                <item
                    android:icon="@drawable/ic_location"
                    android:title="Sub item 2" />
            </group>
        </menu>
    </item>
</menu>
Run Code Online (Sandbox Code Playgroud)

崩溃日志

2020-02-17 12:31:56.719 23527-23527/com.locators.acorn E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.locators.acorn, PID: 23527
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.drawerlayout.widget.DrawerLayout.openDrawer(int)' on a null object reference
    at com.locators.acorn.site.SiteFragment$onCreateView$$inlined$apply$lambda$2.onClick(SiteFragment.kt:46)
    at android.view.View.performClick(View.java:7125)
    at android.view.View.performClickInternal(View.java:7102)
    at android.view.View.access$3500(View.java:801)
    at android.view.View$PerformClick.run(View.java:27336)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Run Code Online (Sandbox Code Playgroud)

Md.*_*man 9

在您的实现中,您不会这样做,因为drawer_layout无法从fragment. 因此你得到了NullPointerException. 尝试按照以下步骤操作:

步骤 - 1:在您Activity的打开-关闭导航抽屉中创建一个函数

fun openCloseNavigationDrawer(view: View) {
    if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
        drawer_layout.closeDrawer(GravityCompat.START)
    } else {
        drawer_layout.openDrawer(GravityCompat.START)
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤 - 2:openCloseNavigationDrawer从您的片段中调用

  • 选项- 1:删除OnClickListener从您的片段代码,并添加onClick通过布局特性,并指出了功能openCloseNavigationDrawersiteDrawerMenuButton
    <ImageView
        android:id="@+id/siteDrawerMenuButton"
        android:onClick="openCloseNavigationDrawer"
        ... />
Run Code Online (Sandbox Code Playgroud)
  • 选项 - 2:您可以openCloseNavigationDrawer通过Activity以下方式通过代码访问该功能:
    siteDrawerMenuButton.setOnClickListener{ v ->
        (activity as YOUR_ACTIVITY).openCloseNavigationDrawer(v)
    }
Run Code Online (Sandbox Code Playgroud)