I'm trying to write a program that sets a file in the Drawable over the ImageView in another fragment when the Button in the BottomSheet is clicked. But i think my context is always null. Because when i tried to add nullability (for example : context?.resources), it doesn't work but the app doesn't crash either. Here is my fragments:
Main Fragment
package com.ahmetkaan.kediy.Fragments
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.res.ResourcesCompat
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.databinding.FragmentNotOlusturBinding
class NotOlustur : Fragment() {
private lateinit var binding : FragmentNotOlusturBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentNotOlusturBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.background.setOnClickListener {
BottomSheet().show(parentFragmentManager, "newTaskTag")
}
}
fun changeBackground0() {
val background = view?.findViewById<ImageView>(R.id.background)
val drawable = ResourcesCompat.getDrawable(requireContext().resources, R.drawable.retrofuture, null)
background?.setImageDrawable(drawable)
}
}
Bottom Sheet Fragment
package com.ahmetkaan.kediy.Fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ahmetkaan.kediy.databinding.FragmentBottomSheetBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class BottomSheet : BottomSheetDialogFragment() {
private lateinit var binding : FragmentBottomSheetBinding
val NotOlustur = NotOlustur()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentBottomSheetBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.imgPrew.setOnClickListener {
NotOlustur.changeBackground0()
}
binding.imgPrew1.setOnClickListener {
}
binding.imgPrew2.setOnClickListener {
}
binding.imgPrew3.setOnClickListener {
}
}
}
Here is the Error Code
java.lang.IllegalStateException: Fragment NotOlustur{1712dba} (eb74f985-d2c2-48d4-93de-d46a66d2e483) not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:967)
at com.ahmetkaan.kediy.Fragments.NotOlustur.changeBackground0(NotOlustur.kt:40)
at com.ahmetkaan.kediy.Fragments.BottomSheet.onViewCreated$lambda-0(BottomSheet.kt:36)
at com.ahmetkaan.kediy.Fragments.BottomSheet.$r8$lambda$mbZWmYt5DwS3MQ-Y8JU1Nc4q61M(Unknown Source:0)
at com.ahmetkaan.kediy.Fragments.BottomSheet$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7297)
at android.view.View.performClickInternal(View.java:7274)
at android.view.View.access$3600(View.java:819)
at android.view.View$PerformClick.run(View.java:28017)
at android.os.Handler.handleCallback(Handler.java:914)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:225)
at android.app.ActivityThread.main(ActivityThread.java:7564)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
You're creating a brand new instance of your NotOlustur
fragment by doing this:
val NotOlustur = NotOlustur()
So, yes, that brand new instance of NotOlustur
was never added to a FragmentManager, just as the error message says.
What you actually want is to get a reference to the fragment that created your BottomSheet
Fragment. To do that, you need to make two changes:
BottomSheet
:BottomSheet().show(childFragmentManager, "newTaskTag")
This is what properly ties your NotOlustur
and BottomSheet
fragments together, rather than being completely independent Fragments in the same FragmentManager. With this change, BottomSheet
will be a child fragment of NotOlustur
.
NotOlustur
fragment by using requireParentFragment()
// Note, variables should generally have a lowercase letter
// so that they are not confused with a Class
val notOlustur get() = requireParentFragment() as NotOlustur
Instead of creating a brand new instance, we can use the correct nesting of the fragments to cast the result from requireParentFragment
as your actual instance of NotOlustur
. The get()
here ensures that this line of code runs only when you actually access the variable, rather than instantly when the Fragment is created.