I am using Navigation Component and inside my home fragment there is a ViewPager2. We knew that viewPager2 contains of Fragment too. How to call parent's function through fragment of viewpager2? I have tried some method like passing function in constructor but i realized the fragment created with singleton mode. I only know how to pass functions in constructor like standart class (Not Singleton class)
My Adapter
class DetailSliderAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
private val images = mutableListOf<String>()
fun addImages(lsImage: List<String>){
images.addAll(lsImage)
notifyDataSetChanged()
}
override fun getItemCount(): Int = images.size
override fun createFragment(position: Int): Fragment {
return SliderImageFragment.newInstance(images[position])
}
class SliderImageFragment: Fragment(){
companion object{
const val EXTRA_SLIDER_IMAGE = "extra_slider_image"
fun newInstance(imageStr: String) = SliderImageFragment().apply {
this.arguments = Bundle().apply {
this.putString(EXTRA_SLIDER_IMAGE, imageStr)
}
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.item_slide_image, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val image = arguments?.getString(EXTRA_SLIDER_IMAGE) as? String
image?.let {
Picasso.get()
.load(image)
.into(image_slide)
image_slide.setOnClickListener {
// here i want to call parent's Fragment function
}
}
}
}
My Fragment home
class DetailFragment : Fragment() {
private var root: View ?= null
private var viewpagerSlider : ViewPager2 ?= null
private val viewModel : DetailViewModel by lazy {
ViewModelProviders.of(this, factory).get(DetailViewModel::class.java)
}
private val adapterSlider : DetailSliderAdapter by lazy {
DetailSliderAdapter(requireActivity()){
//listener
}
}
fun clearAllAdapter(){
// NEED TO CALL THIS
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val safeArgs : DetailFragmentArgs by navArgs<DetailFragmentArgs>()
idProduct = safeArgs.idProduct
Timber.d("ID PRODUCT $idProduct")
if(root == null){
root = inflater.inflate(R.layout.fragment_detail, container, false)
idProduct?.let {
viewModel.getDetail(idProduct!!)
}
}
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Timber.d("CALL onViewCreated")
viewModel.getDataDetail().observe(viewLifecycleOwner, Observer {
when(it.status){
Response.ResponseStatus.LOADED -> {
progress_circular.visibility = View.GONE
val data = it.data
data?.let { d->
val detailProduct = d.detailProduct
detailProduct?.let { pd->
updateUI(pd, data)
}
}
}
}
})
}
private fun updateUI(pd: ProductDetail, data: Data) {
pd.image?.let {
updateSliderPhoto(pd.image)
}
}
private fun updateSliderPhoto(
image: List<String>
) {
viewpagerSlider = root?.findViewById(R.id.slider_photo)
adapterSlider.addImages(image)
viewpagerSlider?.apply {
this.adapter = adapterSlider
this.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback(){
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
page_indicator.text = "${(position+1)}/${image.size}"
}
})
}
}
}
You should never be passing the FragmentActivity
to your FragmentStateAdapter
when in a Fragment
- that's why there's a FragmentStateAdapter
constructor that takes a Fragment
. It is only that Fragment
constructor that properly nests the ViewPager2
fragments in your parent fragment.
Once using the right constructor, your SliderImageFragment
can call requireParentFragment()
and cast it to DetailFragment
and call your method.