问题
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.
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
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 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
<?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
<?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)
回答1:
In your implementation, you don't do that as drawer_layout
is not accessible from fragment
. Hence you got NullPointerException
. Try to follow below steps:
Step - 1: Create a function in your Activity
to open-close 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
- Option - 1: Remove
OnClickListener
from your fragment code and addonClick
property through layout and pointed out the functionopenCloseNavigationDrawer
onsiteDrawerMenuButton
.
<ImageView
android:id="@+id/siteDrawerMenuButton"
android:onClick="openCloseNavigationDrawer"
... />
- Option - 2: You can access the function
openCloseNavigationDrawer
through code by casting yourActivity
like below:
siteDrawerMenuButton.setOnClickListener{ v ->
(activity as YOUR_ACTIVITY).openCloseNavigationDrawer(v)
}
来源:https://stackoverflow.com/questions/60262106/open-navigation-drawer-from-button-click-within-fragment-kotlin