Kotlin: How to call getSupportFragmentManager() in RecyclerView.Adapter - android

I would like to call the Support Fragment Manager in my RecyclerView.Adapter after the click event in order to move to a different fragment. My approach:
(context as MainActivity).supportFragmentManager
.beginTransaction()
.replace(MainActivity.FRAGMENT_CONTAINER, TextScreen())
.commit()
But I get the following error:
kotlin.TypeCastException: null cannot be cast to non-null type
Can you help me?

Updated for 2021 - Kotlin Answer
If you want to call "supportFragmentManager" in Fragment
activity.supportFragmentManager

This is because your Context instance in the adapter is not guaranteed to be an Activity. It could potentially be a ContextWrapper holding the Activity as a base Context. Attempting to unwrap this would be fragile.
Instead, I would recommend that you define an interface in your adapter. From your Activity, provide an implementation of this interface to your adapter that will perform the FragmentTransaction. For example:
class MyAdapter : RecyclerView.Adapter<MyType> {
private var listener: (() -> Unit)? = null
fun setListener(listener: (() -> Unit)?) {
this.listener = listener
}
// wherever your onClick is handled:
listener?.invoke()
}
Then, in the Activity that's initializing MyAdapter:
myAdapter.setListener {
supportFragmentManager
.beginTransaction()
.replace(MainActivity.FRAGMENT_CONTAINER, TextScreen())
.commit()
}

I suggest you handle your fragment transaction in your fragment/activity. This would help you to have cleaner code and using context in fragment/activity is much easier. Try to define the interface between your adapter and fragment and call your interface method in the adapter and implement the interface in activity/fragment. There you can access context easily.

get the activity or fragment as argument in your adapter.
class ArticleAdapter(private val articleActivity: ArticleActivity, private val docs: List<ArticleResult.ArticleDoc>) : RecyclerView.Adapter<ArticleAdapter.Holder>() {
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): Holder = Holder(LayoutInflater.from(p0.context).inflate(R.layout.row_general2, p0, false))
override fun getItemCount(): Int = docs.size
override fun onBindViewHolder(holder: Holder, position: Int) {
articleActivity.supportFragmentManager
}
class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textViewTitleRow = itemView.findViewById<TextView>(R.id.textViewTitleRow)!!
val textView1Row = itemView.findViewById<TextView>(R.id.textView1Row)!!
val textView2Row = itemView.findViewById<TextView>(R.id.textView2Row)!!
val imageViewDownloadRow = itemView.findViewById<ImageView>(R.id.imageViewDownloadRow)!!
val textViewMoreRow = itemView.findViewById<TextView>(R.id.textViewMoreRow)!!
val imageViewBookRow = itemView.findViewById<ImageView>(R.id.imageViewBookRow)!!
}
}

Related

Kotlin access activity on recyclerView Adapter

I have recyclerView and after click of card I would like to replace fragments in activity. The problem is I have no access to activity. Here is my code in adapter:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemsViewModel = mList[position]
holder.tagImage.setImageResource(itemsViewModel.tagImage)
holder.tagName.text = itemsViewModel.tagName
holder.tagDescription.text = itemsViewModel.tagDescription
holder.itemView.setOnClickListener {
Log.d(InTorry.TAG, itemsViewModel.tagName)
val fragment = ProductsFragment()
val transaction = activity?.supportFragmentManager?.beginTransaction()
transaction?.replace(R.id.homeFragmentsContainer, fragment)
//transaction?.disallowAddToBackStack()
transaction?.commit()
}
}
The above replace code works in fragment but in adapter there is "activity?" error.
Kind Regards
Jack
There are multiple ways to solve this problem.
Using Context
You can use the context from holder.itemView and cast it into an Activity.
This is probably the simplest way, however this can be problematic since a Context may represent an Activity, a Service, an Application, etc. in which case it may lead to a ClassCastException when used simply.
Using Callback
You can set up a callback from your Adapter to your Activity or Fragment and then replace your Fragment.
Use JetPack Navigation
This is my personal favorite as the latest versions allow you to access NavController from Activity, Fragment or any View in the hierarchy to navigate. This is just one of many benefits of using this library.
Here is a link to Jetpack Navigation.
The Simplest and Safer way to solve this is my using Callback from your holder to activity. Below is the step by step process :
Decalare an Interface
interface OnItemClick {
fun onClick()
}
Implement that interface in you Activity and put the desired code
class MainActivity : OnItemClick {
...
override onClick() {
// Do whatever you want
val fragment = ProductsFragment()
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.homeFragmentsContainer, fragment)
transaction.commit()
}
}
Create a variable of that Interface type in you Adapter and in your onBindViewHolder method invoke that interface
class MyAdapter(val listener : OnItemClick) {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
...
listener.onClick()
}
Finally pass that interface to your Adapter from you Activity
class MainActivity : OnItemClick {
val adapter = MyAdapter(this)
...
}
NOTE : Please don't pass activity to context here and there you will get unexpected result and most probably a crash.
After watching this video https://www.youtube.com/watch?v=WqrpcWXBz14
I managed to do it this way
In Adapter
class TagsAdapter(var mList: List<TagsViewModel>) :
RecyclerView.Adapter<TagsAdapter.ViewHolder>() {
var onItemClick: ((TagsViewModel) -> Unit)? = null//click listener STEP 1!!!
override fun onBindViewHolder(holder: TagsAdapter.ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
onItemClick?.invoke(itemsViewModel)//click listener STEP 2!!!
}
}
}
And in Fragment
class TagsFragment : Fragment() {
private lateinit var tagsRecyclerView: RecyclerView
private var tagsArray = ArrayList<TagsViewModel>()
private lateinit var adapter: TagsAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = TagsAdapter(tagsArray)
tagsRecyclerView.adapter = adapter
adapter.onItemClick = {//click listener STEP 3!!!
val fragment = ProductsFragment()
val transaction = activity?.supportFragmentManager?.beginTransaction()
transaction?.replace(R.id.homeFragmentsContainer, fragment)
//transaction?.disallowAddToBackStack()
transaction?.commit()
}
}
}
It looks very clean and easy. I don't know is a correct way but it works

Using onClickListener in Recycler View with Retrofit Structure - Kotlin

Hello i have a recyclerview that is filled with some data coming from a Webservice, using Retrofit.
Now I want to implement a onClickListener, so when i click each row of the Recycler View, i can see more data from that object, and tried to work with some examples, but i got stucked
Here is my adapter. I know that in the onCreateViewHolder, i should put in the Return AnunciosViewHolder a second parameter, of the type cellClickListener, but i have no idea what i have to put. I tried this#CellCLickListener and this#cellCLickListener and it gave me error that is is unresolved
class AnuncioAdapter(val anuncios: List<Anuncio>): RecyclerView.Adapter<AnunciosViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnunciosViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerline, parent, false)
return AnunciosViewHolder(view)
}
override fun getItemCount(): Int {
return anuncios.size
}
override fun onBindViewHolder(holder: AnunciosViewHolder, position: Int) {
return holder.bind(anuncios[position])
}
}
class AnunciosViewHolder(itemView : View, private val cellClickListener: CellClickListener): RecyclerView.ViewHolder(itemView){
private val morada: TextView = itemView.findViewById(R.id.morada)
private val telemovel: TextView = itemView.findViewById(R.id.number)
private val fotografia: ImageView = itemView.findViewById(R.id.image)
fun bind(anuncio: Anuncio) {
morada.text = anuncio.morada
telemovel.text = anuncio.telemovel
itemView.setOnClickListener {
cellClickListener.onCellClickListener(anuncio)
}
I also tried creating an interface
interface CellClickListener {
fun onCellClickListener (data: Anuncio)
}
and in my Activity i put this method and it gives me an error that «overrides nothing»
override fun onCellClickListener(data: Anuncio) {
val intent = Intent(this#ListaAnuncios, DetalhesActivity::class.java)
intent.putExtra(PARAM_ID, data.id.toString())
intent.putExtra(PARAM_MORADA, data.morada)
intent.putExtra(PARAM_TELEMOVEL, data.telemovel)
startActivityForResult(intent, newAnuncioActivityRequestCode1)
Log.e("***ID", data.id.toString())
}
UPDATE
After using the suggestions made by Praveen i was able to clean my Adapter from errors, however i am struggling in the activity part
if it put
val anuncioAdapter = AnuncioAdapter(anuncios, this)
on the beggining of my On Create, it doesn't recognize «anuncios»
However i am declaring my adapter inside the call.enqueue
recyclerView.apply {
setHasFixedSize(true)
layoutManager =
LinearLayoutManager(this#ListaAnuncios)
adapter = AnuncioAdapter(response.body()!!)
}
And it is asking to pass an instance of cellClickListener here, but if i use «this» in here, it is stated that i am trying to pass an instance of the recycler view instead of the CellClickListener
NEW UPDATE
Forgot to put all the call.enqueue method
call.enqueue(object : Callback<List<Anuncio>> {
override fun onResponse(call: Call<List<Anuncio>>, response: Response<List<Anuncio>>) {
if (response.isSuccessful){
recyclerView.apply {
setHasFixedSize(true)
layoutManager =
LinearLayoutManager(this#ListaAnuncios)
adapter = AnuncioAdapter(response.body()!!)
}
}
}
override fun onFailure(call: Call<List<Anuncio>>, t: Throwable) {
Toast.makeText(this#ListaAnuncios, "${t.message}", Toast.LENGTH_LONG).show()
}
}) }
i tried both approaches of #Praveen and #aligur, but still struggling with asking me to put the instance of Clicklistener as the 2nd parameter, but using «this» is putting the instance of the Recycler View and not of the ClickListener
Thank You in advance
and in my Activity i put this method and it gives me an error that
«overrides nothing»
You are not implementing CellClickListener in your activity. Add CellClickListener after your activity's class name declaration
class MainActivity : AppCompatActivity(), CellClickListener {
}
I know that in the onCreateViewHolder, i should put in the Return
AnunciosViewHolder a second parameter, of the type cellClickListener,
but i have no idea what i have to put. I tried this#CellCLickListener
and this#cellCLickListener and it gave me error that is is unresolved
You've to add the private val cellClickListener: CellClickListener parameter to the constructor of AnuncioAdapter, not the ViewHolder. Only then you will be able to pass it from your activity.
Change constructor of AnuncioAdapter to accept a CellClickListener and remove the same from the constructor of AnunciosViewHolder
class AnuncioAdapter(
private val anuncios: List<Anuncio>,
private val cellClickListener: CellClickListener
): RecyclerView.Adapter<AnunciosViewHolder>() {
}
To access this cellClickListener inside AnunciosViewHolder you've to make it an inner class of AnuncioAdapter, which you can make, as it's already tightly coupled with the adapter.
inner class AnunciosViewHolder(itemView : View): RecyclerView.ViewHolder(itemView){
}
Now, on creating an object of AnuncioAdapter inside activity, just pass an instance of cellClickListener using this, as it's already implementing it.
val anuncioAdapter = AnuncioAdapter(anuncios, this)
I think the easiest way is passing function as parameter to RecyclerViewAdapter.
for instance:
RecyclerViewAdapter(val clickListener : () -> Unit)
onCreateViewHolder(){
clickListener.invoke()
}
in your view
adapter = ReceylerViewAdapter({
//do your stuff here
})
Was finally able to find a solution. By Using #Praveen suggestion, and by finding this example https://github.com/velmurugan-murugesan/Android-Example/tree/master/RetrofitWithRecyclerviewKotlin/app/src/main/java/app/com/retrofitwithrecyclerviewkotlin
On the activity i added a new val, before the OnCreate method
lateinit var anuncioAdapter: AnuncioAdapter
Added this on the onCreate (so i could use the first sugestion)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
anuncioAdapter = AnuncioAdapter(this,this)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = anuncioAdapter
And changed the recyclerview.apply {} on the call.enqeue just to
anuncioAdapter.Anuncios(response.body()!!);
And finally created the Anuncios Method on the Adapter
fun Anuncios(anuncio: List<Anuncio>){
this.anuncios = anuncio;
notifyDataSetChanged()
}
With this it works like how i wanted id. Thanks for the help

Add Listener into ViewHolder for fragement to communication with Activity

I am trying to trigger the start of a fragment B when a click is detected on an item from the Recycler view present in the Fragment A.
The way I did it is:
MainActivity start the Fragement A and display a list of CardView
Once the user click on one of the CardView, an interface call a click method implemented in the main Activity to start the Fragment B
MainActivity.kt
class MainActivity : AppCompatActivity(), OnLocationSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(savedInstanceState == null) { // initial transaction should be wrapped like this
--Start Fragment A
}
}
override fun onLocationSelected(id: String) {
replaceFragment(FragmentB(), R.id.listcontainer, id)
}
companion object {
val LOCATION_ID: String = "location_id"
}
}
The interface is defined in : OnLocationSelectedListener.kt
interface OnLocationSelectedListener {
fun onLocationSelected(id: String)
}
the listener must be called from the Adapter linked to Fragment B
class FragmentBAdapter(
var listOfLocations: List<RestaurantLocation>) : RecyclerView.Adapter<LocationsListAdapter.ViewHolder>() {
private lateinit var onLocationSelectedListener: OnLocationSelectedListener
override fun getItemCount(): Int {
return listOfLocations.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationsListAdapter.ViewHolder {
return ViewHolder(
parent.context,
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.location_item,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindViewHolder(listOfLocations[position])
}
inner class ViewHolder(private val context: Context, private val viewDataBinding: LocationItemBinding) :
RecyclerView.ViewHolder(viewDataBinding.root) {
fun bindViewHolder(location: RestaurantLocation) {
viewDataBinding.locationName.text = location.name
viewDataBinding.cardItem.setOnClickListener {
onLocationSelectedListener.onLocationSelected(location.id)
}
}
}
}
I have an exception popping up because lateinit property onLocationSelectedListener has not been initialized
I do not understand how to initialize it?
Any idea?
Thanks
You need to pass the listener to the constructor of your FragmentBAdapter, like so:
class FragmentBAdapter(val onLocationSelectedListener: OnLocationSelectedListener)
Your Activity is a OnLocationSelectedListener, so in your Fragment where you create your adapter, probably in onCreateView(), you can just do this
adapter = FragmentBAdapter(activity as? OnLocationSelectedListener)
As you have onLocationSelectedListener's implementation in your MainActivity, you can pass MainActivity's object to FragmentBAdapter and initialize onLocationSelectedListener in FragmentBAdapter's constructor by MainActivity Object

Kotlin Recyclerview ItemClick to new Intent

I have a problem. I can print a toast message when I click on any item in Recyclerview. But I want to switch to a different activity when clicked. Could you please help me in a very specific way? It is a very important project for me. The code blocks I wrote are as follows. Thanks in advance .
CustomersAdapter
class CustomersAdapter(private val companynameArray:ArrayList,private val companyoffArray:ArrayList, private val companyPhoneArray:ArrayList):
RecyclerView.Adapter<CustomersAdapter.CustomerHolder>() {
class CustomerHolder(view: View) : RecyclerView.ViewHolder(view) {
var recycleCompanyName: TextView?=null
var recycleOffName: TextView?=null
var recycleOffPhone: TextView?=null
init {
recycleCompanyName=view.findViewById(R.id.recycleCompanyName)
recycleOffName=view.findViewById(R.id.recycleOffName)
recycleOffPhone=view.findViewById(R.id.recycleOffPhone)
itemView.setOnClickListener {
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomerHolder {
val inflater= LayoutInflater.from(parent.context)
val view= inflater.inflate(R.layout.recycler_view_customer_row,parent,false)
return CustomersAdapter.CustomerHolder(view)
}
override fun getItemCount(): Int {
return companynameArray.size
}
override fun onBindViewHolder(holder: CustomerHolder, position: Int) {
holder.recycleCompanyName?.text="Şirket Adı:"+companynameArray[position]
holder.recycleOffName?.text="Şirket Yetkilisi :"+companyoffArray[position]
holder.recycleOffPhone?.text="İrtibat No : "+companyPhoneArray[position]
}
}
I did not specify the activity I want to go to. I would appreciate it if you could help as a method.
If it helps, I write the codes of the client class here.
class Customers : AppCompatActivity()
{
private lateinit var auth: FirebaseAuth
private lateinit var db: FirebaseFirestore
var companynameFB:ArrayList<String> = ArrayList()
var companyoffFB:ArrayList<String> = ArrayList()
var companyphoneFB:ArrayList<String> = ArrayList()
var adapter :CustomersAdapter?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_customers)
auth= FirebaseAuth.getInstance()
db= FirebaseFirestore.getInstance()
getDataFromFirestore()
var layoutManager= LinearLayoutManager(this)
recyclerView.layoutManager=layoutManager
adapter= CustomersAdapter(companynameFB,companyoffFB,companyphoneFB)
recyclerView.adapter=adapter
}
fun getDataFromFirestore(){
db.collection("Customers")
.addSnapshotListener { snapshot, exception ->
if(exception!=null){
Toast.makeText(applicationContext,exception.localizedMessage.toString(),Toast.LENGTH_LONG).show()
}else{
if(snapshot!=null){
if (!snapshot.isEmpty){
companynameFB.clear()
companyoffFB.clear()
companyphoneFB.clear()
val documents=snapshot.documents
for (document in documents){
val compname=document.get("compname") as String
val compoff=document.get("compoff") as String
val compphone=document.get("compphone") as String
val user=document.get("user") as String
val timeStamp=document.get("date") as Timestamp
val date=timeStamp.toDate()
companynameFB.add(compname)
companyoffFB.add(compoff)
companyphoneFB.add(compphone)
adapter!!.notifyDataSetChanged()
}
}
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val menuInflater=getMenuInflater()
menuInflater.inflate(R.menu.add_customer,menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item.itemId==R.id.add){
val intent= Intent(this,AddCustomers::class.java)
intent.putExtra("info","new")
startActivity(intent)
}
return super.onOptionsItemSelected(item)
}
For starting a new Activity you need at least a context instance. And as is written in some other answers here, you could start the activity directly inside ViewHolder with View's context. But for better separations of responsibilities, I suggest you move your navigation to your Fragment/Activity, where all other navigations happen. That way you know at the look of Activity/Fragment, which navigations could be done from that screen, and you don't need to search for some hidden navigations that happen inside Adapter or ViewHolder. Also, if you need to perform startActivityForResult, then an instance of Context is not enough to do that. You need an Activity or Fragment instance for that and we have another reason to put all navigations there.
So you can do this like that:
ADD LAMBDA TO ADAPTER CONSTRUCTOR:
class CustomersAdapter(private val companynameArray: ArrayList,
private val companyoffArray: ArrayList,
private val companyPhoneArray: ArrayList,
private val onItemClick: () -> Unit) : RecyclerView.Adapter<CustomersAdapter.CustomerHolder>() {
NOTE: put lambda as the last constructor parameter.
ADD LAMBDA TO VIEWHOLDER CONSTRUCTOR:
class CustomerHolder(view: View,
private val onItemClick: () -> Unit) : RecyclerView.ViewHolder(view) {
MODIFY VIEWHOLDER CONSTRUCTOR CALL:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomerHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.recycler_view_customer_row,parent,false)
return CustomersAdapter.CustomerHolder(view, onItemClick) //Add onItemClick lambda instance from adapter here
}
INVOKE LAMBDA ON CLICK:
itemView.setOnClickListener {
onItemClick()
}
FIX ADAPTER CONSTRUCTOR CALL:
val adapter = CustomersAdapter(companynameArray, companyoffArray, companyPhoneArray) {
startActivity() // do your navigation here
}
Why did we place lambda as the last parameter of a constructor in our adapter? If the last parameter of a function is a function, then a lambda expression passed as the corresponding argument can be placed outside the parentheses(SOURCE). And we did exactly that with the last junk of code above where we handle our navigation.
put your click listener inside onBindViewHolder method
override fun onBindViewHolder(holder: CustomerHolder, position: Int) {
holder.recycleCompanyName?.text="Şirket Adı:"+companynameArray[position]
holder.recycleOffName?.text="Şirket Yetkilisi :"+companyoffArray[position]
holder.recycleOffPhone?.text="İrtibat No : "+companyPhoneArray[position]
holder.itemView.setOnClickListener {
// do what ever you want here
holder.itemView.context.startActivity( /*your intent here*/)
}
}
}
Step 1 : pass context here
class CustomersAdapter(val context:Context,private val
companynameArray:ArrayList,private val
companyoffArray:ArrayList, private val companyPhoneArray:ArrayList):
RecyclerView.Adapter<CustomersAdapter.CustomerHolder>() {
step 2:
itemView.setOnClickListener {
val intent=Intent(context,yourActivity::java.class)
startActivity(intent)
}
you need a context for intent so you can get it form the activity or fragment that are associated with this adapter and pass it to your intent or you can get it from any view in your inflated layout like this
val context=holder.title.context
val intent = Intent( context, EventDetail::class.java)
context.startActivity(intent)

How to get Current Fragment in ViewPager2 [duplicate]

This question already has answers here:
Get current fragment with ViewPager2
(18 answers)
Closed 1 year ago.
i used this ViewPager2 dependency:
implementation 'androidx.viewpager2:viewpager2:1.0.0'
then i wrote code and make Adapter for FragmentStateAdapter like below:
private inner class ViewPagerAdapter(fragmentManager: FragmentManager,
lifecycle: Lifecycle, config: TribunConfig?)
: FragmentStateAdapter(fragmentManager, lifecycle) {
private val config: TribunConfig?
override fun createFragment(position: Int): Fragment {
return TribunNewsFragment.newInstance(if (menuTribun!!.get(position) == "News") "home"
else menuTribun!!.get(position)!!.replace(" ", "").toLowerCase(), config)!!
}
override fun getItemCount(): Int {
return menuTribun!!.size
}
init {
this.config = config
}
}
an in method onCreate i implement some code related viewpager2 and its adapter like below:
viewPager2!!.offscreenPageLimit = 1
viewPager2!!.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, config)
TabLayoutMediator(tabLayout!!, viewPager2!!, TabLayoutMediator.TabConfigurationStrategy { tab: TabLayout.Tab?, position: Int -> tab!!.text = menuTribun!!.get(position) }).attach()
But i have problem when i want to make swipeRefresh. My swipeRefresh needs current fragment to access the method inside fragment. But there is NO METHOD getItem in FragmentStateAdapter. Anyone can help me?
Create property in your adapter to save all your fragments
Save current position
Get fragment from fragment list (property) by position when you need it
Something like this:
val fragments: MutableList<Fragment> = mutableListOf()
private val config: TribunConfig?
override fun createFragment(position: Int): Fragment {
val fragment = TribunNewsFragment.newInstance(if (menuTribun!!.get(position) == "News") "home"
else menuTribun!!.get(position)!!.replace(" ", "").toLowerCase(), config)!!
fragments.add(fragment)
return fragment
}
Parent:
yourTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
val fragment = adapter.fragments[tab!!.position]
// cast fragment to your fragment class and do what you want
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
}
override fun onTabReselected(tab: TabLayout.Tab?) {
}
})
Also you can use when or if-else for your fragments position or create base class with methods you need and cast getting fragment to it.
Following #Oleg's answer, you can access the Fragments like this in your Adapter instead of creating a local list and adding each fragment on createFragment method:
private val fragmentList: List<TribunNewsFragment>
get() {
return fragment.childFragmentManager.fragments.filterIsInstance<TribunNewsFragment>()
}
It's important to use childFragmentManager instead of fragmentManager if you are creating the ViewPager inside another fragment.
And it survives configuration changes, regarding #lawonga's comment on the answer's topic.

Categories

Resources