简体   繁体   English

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

[英]Open Navigation Drawer from Button Click within Fragment (Kotlin)

I have created a custom button in a Fragment and I am trying to open the Navigation Drawer in the Activity when it is clicked.在 Fragment 中创建了一个自定义按钮我试图单击它时在 Activity 中打开导航抽屉。

The Navigation Drawer still opens ok when you swipe across, but the app just crashes when I click the button.当您滑动时,导航抽屉仍然可以正常打开,但是当我单击按钮时应用程序崩溃了。

I guess this is because I am trying to access from the Fragment, but I am at a loss..我想这是因为我试图从 Fragment 访问,但我不知所措..

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
}

activity.xml活动.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>

site_fragment.xml site_fragment.xml

 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/siteMainConstraintLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" tools:context=".site.SiteActivity" > <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/siteLogoConstraintLayout" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginTop="16dp" android:foregroundGravity="center_horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <ImageView android:id="@+id/siteLogoImage" android:layout_width="50dp" android:layout_height="match_parent" android:src="@mipmap/ic_launcher_logo" app:layout_constraintEnd_toStartOf="@id/siteTopHeadingText" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/siteTopHeadingText" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:paddingStart="12dp" android:paddingLeft="12dp" android:text="@string/site_top_heading" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textSize="18sp" android:textStyle="bold|italic" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> <ImageView android:id="@+id/siteOverflowOptionsMenuButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" app:srcCompat="@drawable/ic_menu_vertical_dots" android:tint="@color/locatorsPurpleCompany" app:layout_constraintBottom_toBottomOf="@+id/siteLogoConstraintLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/siteLogoConstraintLayout" /> <ImageView android:id="@+id/siteDrawerMenuButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" app:srcCompat="@drawable/ic_menu_drawer" android:tint="@color/locatorsPurpleCompany" app:layout_constraintBottom_toBottomOf="@+id/siteLogoConstraintLayout" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/siteLogoConstraintLayout" /> <androidx.cardview.widget.CardView android:id="@+id/siteFilterOptionsCardView" android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginRight="8dp" app:cardBackgroundColor="@color/locatorsGrey" app:cardCornerRadius="18dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/siteLogoConstraintLayout"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/siteFilterOptionsConstraintLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/siteFilterIconImageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginLeft="8dp" app:srcCompat="@drawable/ic_filter" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/siteCurrentFilterTextView" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="8dp" android:layout_marginLeft="8dp" android:layout_marginTop="4dp" android:layout_marginEnd="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="4dp" android:background="@color/white" android:drawableLeft="@drawable/ic_search" android:drawablePadding="8dp" android:ellipsize="end" android:gravity="center_vertical" android:lines="1" android:paddingLeft="12dp" android:paddingRight="12dp" android:text="Search..." app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/siteClearIconImageView" app:layout_constraintStart_toEndOf="@+id/siteFilterIconImageView" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/siteClearIconImageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginRight="8dp" app:srcCompat="@drawable/ic_clear" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView> <androidx.recyclerview.widget.RecyclerView android:id="@+id/siteRecyclerView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginBottom="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/siteFilterOptionsCardView" app:layout_constraintVertical_bias="0.0" tools:listitem="@layout/site_list_item" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/floatingActionButtonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="32dp" android:layout_marginRight="32dp" android:layout_marginBottom="24dp" android:backgroundTint="@color/locatorsPurpleCompany" android:clickable="true" android:elevation="28dp" app:borderWidth="0dp" app:fabSize="normal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/siteRecyclerView" app:srcCompat="@drawable/ic_add_white" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>

drawer_menu.xml 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>

Crash Log崩溃日志

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)

In your implementation, you don't do that as drawer_layout is not accessible from fragment .在您的实现中,您不会这样做,因为drawer_layout无法从fragment访问。 Hence you got NullPointerException .因此你得到了NullPointerException Try to follow below steps:尝试按照以下步骤操作:

Step - 1: Create a function in your Activity to open-close Navigation Drawer步骤 - 1:在您的Activity创建一个函数来打开-关闭 Navigation Drawer

fun openCloseNavigationDrawer(view: View) {
    if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
        drawer_layout.closeDrawer(GravityCompat.START)
    } else {
        drawer_layout.openDrawer(GravityCompat.START)
    }
}

Step - 2: Invoke openCloseNavigationDrawer from your fragment步骤 - 2:从片段中调用openCloseNavigationDrawer

  • Option - 1: Remove OnClickListener from your fragment code and add onClick property through layout and pointed out the function openCloseNavigationDrawer on siteDrawerMenuButton .选项 - 1:从片段代码中删除OnClickListener并通过布局添加onClick属性并指出openCloseNavigationDrawer上的函数siteDrawerMenuButton
    <ImageView
        android:id="@+id/siteDrawerMenuButton"
        android:onClick="openCloseNavigationDrawer"
        ... />
  • Option - 2: You can access the function openCloseNavigationDrawer through code by casting your Activity like below:选项 - 2:您可以通过如下所示投射您的Activity来通过代码访问函数openCloseNavigationDrawer
    siteDrawerMenuButton.setOnClickListener{ v ->
        (activity as YOUR_ACTIVITY).openCloseNavigationDrawer(v)
    }

A bit late to the party, but in case someone finds this useful - it's a single line with Jetpack Binding:聚会有点晚了,但如果有人发现这很有用 - 它是 Jetpack Binding 的一行:

class LoginViewModel ( applicationParam: Application ) : AndroidViewModel ( applicationParam )
{

    screenViews     = FragmentLoginBinding.inflate ( inflater,container,false )


    override fun onViewCreated ( view: View, savedInstanceState: Bundle? )
    {
        // Set click listener for the Log in button
        screenViews.login.setOnClickListener { submitLogin() }

        // Set the click listener for the element that selects the register fragment from the navigation drawer
        screenViews.goToRegisterFragment.setOnClickListener { findNavController().navigate ( R.id.nav_register ) }

    }
}

With LoginViewModel being the view model for a fragment called Login, and R_id_nav_register being an element in mobile_navigation.xml and activity_main_drawer.xml LoginViewModel 是名为 Login 的片段的视图模型,R_id_nav_register 是 mobile_navigation.xml 和 activity_main_drawer.xml 中的一个元素

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM