Below is my code which has 3 Fragment classes
each embedded with each of the 3 tabs on ViewPager
. I have a menu option. As shown in the onOpt
Based on what he answered @chahat jain :
"When we use the viewPager, a good way to access the fragment instance in activity is instantiateItem(viewpager,index). //index- index of fragment of which you want instance."
If you want to do that in kotlin
val fragment = mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
if ( fragment is YourFragmentFragment)
{
//DO somthign
}
0 to the fragment instance of 0
//=========================================================================// //#############################Example of uses #################################// //=========================================================================//
Here is a complete example to get a losest vision about
here is my veiewPager in the .xml file
...
<android.support.v4.view.ViewPager
android:id="@+id/mv_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"/>
...
And the home activity where i insert the tab
...
import kotlinx.android.synthetic.main.movie_tab.*
class HomeActivity : AppCompatActivity() {
lateinit var adapter:HomeTabPagerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
}
override fun onCreateOptionsMenu(menu: Menu) :Boolean{
...
mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
...
override fun onQueryTextChange(newText: String): Boolean {
if (mv_viewpager.currentItem ==0)
{
val fragment = mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
if ( fragment is ListMoviesFragment)
fragment.onQueryTextChange(newText)
}
else
{
val fragment = mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 1) as Fragment
if ( fragment is ListShowFragment)
fragment.onQueryTextChange(newText)
}
return true
}
})
return super.onCreateOptionsMenu(menu)
}
...
}
Override setPrimaryItem from your FragmentPagerAdapter: the object is the visible fragment:
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (mCurrentFragment != object) {
mCurrentFragment = (LeggiCapitoloFragment) object;
}
super.setPrimaryItem(container, position, object);
}
In my previous implementation I stored a list of child Fragments to be able to access them later, but this turned out to be a wrong implementation causing huge memory leaks.
I end up using instantiateItem(...)
method to get current Fragment:
val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)
Or to get any other Fragment on position:
val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)
From documentation:
Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns from finishUpdate(ViewGroup).
I had the same issue and solved it using this code.
MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container);
Just replace the name MyFragment with the name of your fragment and add the id of your fragment container.
FragmentStatePagerAdapter has public method with the name instantiateItem that return your fragment based on specified parameter values, this method has two parameters ViewGroup (ViewPager) and position.
public Object instantiateItem(ViewGroup container, int position);
Used this method to get specified position's fragment,
Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position);
The scenario in question is better served by each Fragment adding its own menu items and directly handling onOptionsItemSelected(), as described in official documentation. It is better to avoid undocumented tricks.