I'm trying to add/remove dynamically fragments in a ViewPager following a button click, but if I remove the fragment (a form) by clicking on back button, and add the fragment again, the form has kept its data (EditText not empty).
Here is my adapter :
package com.thomas.playlists.viewPager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
public class ViewPagerAdapter extends FragmentPagerAdapter
{
ArrayList<Fragment> mList = null;
public ViewPagerAdapter(FragmentManager fm)
{
super(fm);
mList = new ArrayList<Fragment>();
}
public void add(Fragment fragment)
{
mList.add(fragment);
}
public void removeLast()
{
if(mList.size() > 1)
mList.remove(getCount() - 1);
}
#Override
public Fragment getItem(int i)
{
return mList.get(i);
}
#Override
public int getCount()
{
return mList.size();
}
}
Adding proccess used twice (in main Activity) :
PlaylistFragment playlistFragment = new PlaylistFragment();
mViewPagerAdapter.add(playlistFragment);
mViewPagerAdapter.notifyDataSetChanged();
mViewPager.setCurrentItem(mViewPagerAdapter.getCount() - 1, true);
Removing a page (still in main Activity) :
mViewPagerAdapter.removeLast();
mViewPagerAdapter.notifyDataSetChanged();
mViewPager.setCurrentItem(mViewPagerAdapter.getCount() - 1, true);
How can I remove the fragment properly ?
EDIT : I tried this but the form isn't reseted;
EDIT 2 : After instanciating the second fragment, its onCreate() method isn't called.
Extend FragmentStatePagerAdapter, and override getItemPosition methode:
public class ViewPagerAdapter extends FragmentStatePagerAdapter
{
//... your existing code
#Override
public int getItemPosition(Object object) {
int position = mList.indexOf(object);
return position == -1 ? POSITION_NONE : position;
}
}
Related
first this is my Activity
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
viewpager = (ViewPager)findViewById(R.id.pager);
swipeadapter = new swipeadapter(this);
viewpager.setAdapter(swipeadapter);
//some condition remove textview or hide textview from current Pagerview
//position
//if(mm = oo){ //remove item from current pagerView adapter }
}
}
and this my adapter code
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.util.SparseArray;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.Calendar;
import ws.design.com.R;
public class swipeadapter extends PagerAdapter {
private Context ctx;
private LayoutInflater layoutInflater;
private LinearLayout player;
SparseArray<Fragment> registeredFragments = new SparseArray<>();
public swipeadapter(Context c){
this.ctx = c;
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
#Override
public boolean isViewFromObject(View view, Object o) {
return (view == (LinearLayout)o);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
container.removeView((LinearLayout)object);
}
public void changeVisiblityOfTextView(int visiblity)
{
player.setVisibility(View.GONE);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
layoutInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View inflatedView = layoutInflater.inflate(R.layout.player, container,false);
player = (LinearLayout)inflatedView.findViewById(R.id.buttons);
Display display = ((Activity)ctx).getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
container.addView(inflatedView);
return inflatedView;
}
#Override
public int getCount() {
return 10;
}
void setSimpleList(ListView listView){
ArrayList<String> contactsList = new ArrayList<String>();
for (int index = 0; index < 10; index++) {
contactsList.add("I am # index " + index + " today " + Calendar.getInstance().getTime().toString());
}
listView.setAdapter(new ArrayAdapter<String>(ctx,
R.layout.fb_comments_list_item, android.R.id.text1,contactsList));
}
}
i have pagerView and its work currently good but i want to hide item in current PagerView position thats shown to user if condition true how can i hide textView with id hideThis from this activity Main
Define a SparseArray in your ViewPager's adapter to keep fragment instances like below:
SparseArray<Fragment> registeredFragments = new SparseArray<>();
Note: Why SparseArray? https://developer.android.com/reference/android/util/SparseArray.html
Override instanstiateItem method of your FragmentPagerAdapter like below:
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
And override DestroyItem method:
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
Define a method to get current fragment like below:
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
Define a public method to change visibility of your TextViews in Fragmentsif your condition is True
public void changeVisiblityOfTextView(int visiblity)
{
mTextView.setVisiblity(visibility);
}
Add a new onPageChangeListener to your ViewPager:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
YourFragment fragment = (YourFragment)yourPagerAdapter.getRegisteredFragment(position);
if(yourCondition){
fragment.changeVisiblityOfTextview(View.VISIBLE);
}
else{
fragment.changeVisiblityOfTextView(View.GONE)
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I hope my answer helps you. Good Luck!
Edit:
YourPagerAdapter: FragmentPagerAdapter or FragmentStatePagerAdapter which you set to view pager.
YourFragment: It's your custom fragment which you extend from Support.Fragment and use in your view pager. (Fragment which you return in your adapter's public Fragment getItem(int position) method.
It's basically you add your fragment instances in a sparse array when you init return a new fragment in your view pager and get it to from adapter to change visibility of items which you put in your fragment.
I assume that your textview's in your view pager fragment's layout.
Edit 2:
Ops you do not use Fragments in your ViewPager so my solution is not suitable for you. You can change your ViewPager implementation to fragments or instead of keeping fragments in sparse array you can keep your inflated views which you add to container and instead of fragments you can go on with that views. And in onPageChanged method you can get view as in my example, find your textview and change it's visibility.
When i have time i'll add code here.
If you want to remove an item from your ViewPager, you need to remove it from the PagerAdapter and call notifyDatasetChanged() then set the adapter to the ViewPager again:
mAdapter.removeItem(position);
mViewPager.setAdapter(mAdapter);
You need to add a removeItem method in your adapter class (or however you want to remove the item):
public class MyAdapter extends PagerAdapter {
//...
public void removeItem(int position) {
if (position > -1 && position < items.size()) {
items.remove(position);
notifyDataSetChanged();
}
}
//...
}
This is the only way I got the ViewPager to refresh and fully remove the view in question.
You can store the current ViewPager position just before you remove the item and set the ViewPager to that position again.
I have a ViewPager that works well, but I want to make it a little better.
Right now in my PagerAdapter class, in the getItem method I use a switch statement:
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabFragmentChicken tabChicken = new TabFragmentChicken();
return tabChicken;
case 1:
TabFragmentFish tabFish = new TabFragmentFish();
return tabFish;
...
And then over in my activity class, I set the tabs name like so:
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Chicken"));
tabLayout.addTab(tabLayout.newTab().setText("Fish"));
...
Is there a way I can better modularize this? For instance if I wanted to change the order of the tabs I'd have to change both the switch statement and the tab names. Is there another class or structure I can use to keep it all in one place so I only need to update one thing and not have to bother with the switch/adding tab text changes?
You can create a custom Object that will hold the title and the fragment, then use a list of this Object within your adapter. Here is a small way of implementing it:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.chahinemouhamad.parrrot.home.recent.RecentFragment;
public class HomePagerAdapter extends FragmentPagerAdapter {
private final PagerFragment[] pagerFragments;
public HomePagerAdapter(final FragmentManager fm) {
super(fm);
pagerFragments = new PagerFragment[] {
new PagerFragment("item 1", RecentFragment.newInstance()),
new PagerFragment("item 2", RecentFragment.newInstance())
};
}
#Override public Fragment getItem(final int position) {
return pagerFragments[position].fragment;
}
#Override public int getCount() {
return pagerFragments.length;
}
#Override public CharSequence getPageTitle(final int position) {
return pagerFragments[position].title;
}
class PagerFragment {
public final String title;
public final Fragment fragment;
public PagerFragment(String title, Fragment fragment) {
this.title = title;
this.fragment = fragment;
}
}
}
I used a TabLayout for a tabbed view in my app. I added three List fragments - one for each tab.
The content of either of the fragments is supposed to be changed (and the list views have to be updated) when new record is added/removed from any of the fragments.
But after I modify some data and swiped to the next tab the list view is not updated and retained the old data.
I created an interface that is implemented in all of the ListFragments as follows:
public interface UpdatableFragment {
void updateContent();
}
public class LogFragment implements UpdatableFragment{
...
#Override
public void updateContent() {
Activity activity = getActivity();
if (isAdded() && activity != null) {
getLoaderManager().restartLoader(LOG_LIST_LOADER, null, this);
}
}
...
}
And I call the method in the MainActivity tab select listener
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
if(adapter != null){
int position = viewPager.getCurrentItem();
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setCurrentItem(position);
Fragment tabbedFragment = adapter.getItem(viewPager.getCurrentItem());
if(tabbedFragment instanceof UpdatableFragment){
((UpdatableFragment) tabbedFragment).updateContent();
}
}
}
But the condition if (isAdded() && activity != null) in updateContent() method sometimes returns false because activity becomes null. On other times, it returns the MainActivity instance and the loader restarts.
Why is this inconsistent behavior happening and how can I make the ListFragments always show fresh content when their corresponding tabs are selected?
EDIT
adding the fragment pager code
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
The getItem(int position) method does not return a reference to the Fragment currently in that position of your ViewPager. The getItem() method is used in the PagerAdapter when it calls instantiateItem() to create your views/fragments, so when you call getItem(int position) it's creating a brand new Fragment for you, and this is not added/attached to your Activity (causing the false/null in your if check). If you look into the code for FragmentPagerAdapter.instantiateItem() you can see where it calls getItem() and then adds the Fragment with the FragmentManager.
One way to get around this is to cache your Fragment references in your FragmentPagerAdapter (do this by caching the Fragment returned by instantiateItem() and remove the references in adapter.destroyItem()), or calling adapter.notifyDataSetChanged() to re-create your views with the updated data.
UPDATE:
You want to add something like this to your FragmentPagerAdapter:
public class Adapter extends FragmentPagerAdapter {
private SparseArray<Fragment> fragmentCache = new SparseArray<>();
#Override public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
fragmentCache.put(position, fragment);
return fragment;
}
#Override public void destroyItem(ViewGroup container, int position, Object object) {
fragmentCache.remove(position);
super.destroyItem(container, position, object);
}
// other code....
}
You can then get references to all the fragments currently in your adapter from the fragmentCache, and then you can call your updateContent method on them.
I have an application with tabhost and viewpager.
I have one tab, fragment as fixed.
I have to add tab,fragments dynamically on click radio button in radiogroup from the first fragment.
MyPagerAdapter class:
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
public class MyViewPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments = new ArrayList<Fragment>();
FragmentManager fm;
public List<Fragment> getFragments() {
return fragments;
}
public void setFragments(List<Fragment> fragments) {
this.fragments = fragments;
}
public MyViewPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fm = fm;
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
public void addFragment(Fragment fragment) {
this.fragments.add(fragment);
notifyDataSetChanged();
}
public void removeFragments() {
try {
List<Fragment> newList = new ArrayList<Fragment>();
Fragment general = fragments.get(0);
newList.add(general);
this.fragments.clear();
this.fragments = new ArrayList<Fragment>();
this.fragments = newList;
notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
public void removeItemFromFrament(ViewGroup container, int position, Object object) {
try {
try {
container.removeViewAt(position);
((ViewPager) container).setCurrentItem(position - 1);
} catch (Exception e) {
e.printStackTrace();
}
notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyPagerFragment class:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MyViewPageFragment extends Fragment {
private static View mView;
public static final MyViewPageFragment newInstance(int layoutId) {
MyViewPageFragment f = new MyViewPageFragment();
Bundle b = new Bundle();
b.putInt("layout", layoutId);
f.setArguments(b);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int layout = getArguments().getInt("layout");
try {
mView = inflater.inflate(layout, container, false);
} catch (Exception e) {
}
return mView;
}
}
Im trying to add fragments to adapter like this:
Fragment fragment = MyViewPageFragment.newInstance(R.layout.tab_content_layout);
((MyViewPageAdapter) mViewPager.getAdapter()).addFragment(fragment);
My Problem:
On first time, the pages are added properly, after remove all views(except first fragment) and trying to add another set of tabs, fragments the views are not visible and the getSupportFragmentmanager.getFragments().size() is incorrect.
I tried to remove the views from viewpager with fragment manager
FragmentManager manager = ((Fragment) object).getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove((Fragment) object);
trans.commit();
After adding tabs, fragments on pagescrolled the getSupportFragmentManager().getFragments.get(arg0) returns null.
Note:
I have to maintain the state of the first fragment, so FragmentStatePagerAdapter and getItemPosition return POSITION_NONE is not acceptable.
In the same way that you don't specifically call removeView() on a ListView from a ListAdapter to get rid of an item, you don't directly remove a Fragment with FragmentManager from a FragmentPagerAdapter.
You have to override getItemPosition(), but you have to provide a little more intelligent implementation than just returning POSITION_NONE all the time.
If your first fragment never changes, then always return POSITION_UNCHANGED when that fragment is passed to getItemPosition()
Think about it as a conversation between you and the ViewPager/FragmentPagerAdapter. Here's an example:
You: "I need to change the fragments around." (call notifyDataSetChanged)
Adapter: "Heads up, I'm going to change everything around now." (callback startUpdate)
Adapter: "How many tabs do you want?" (callback getCount())
You: Three. (return '3')
Adapter: "Okay, what do you want me to do with this first one?" (callback getItemPosition)
You: "I want to keep that one right where it is." (return POSITION_UNCHANGED)
Adapter: "Great, what about this second one?" (callback getItemPosition)
You: "I want to move it to the third tab." (return '2')
Adapter: "All right, what about the third one?" (callback getItemPosition)
You: "I want to get rid of that one completely." (return POSITION_NONE)
Adapter: "Okay, I have a space for the second tab, what fragment do you want me to use?" (callback getItem)
You: "This one." (return fragment for position == 1)
Adapter: "I'm done changing everything, kthxbye." (callback finishUpdate)
I might not have the order of calls exactly right, but the basic idea is there.
If you need to maintain the state of the fragments that are kicked out, you could override getItem() and destroyItem() to help you with that:
private FragmentManager mFragmentManager;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
mFragmentManager = fm;
}
#Override
public Fragment getItem(int position) {
// figure out which fragment you want at this position
Fragment fragment = new MyFragment();
// retrieve your savedState from wherever you put it
fragment.setInitialSavedState(savedState);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
Fragment.SavedState savedState = mFragmentManager.saveFragmentInstanceState(fragment)
// save your fragment state somewhere here
super.destroyItem(container, position, object);
}
Your fragments will need to implement saveState() and restoreState() for this to work.
I tried similar requirement as yours with a FragmentStatePagerAdapter which worked fine. May be it could help you.
To add the new fragment:
SIZE = SIZE +1;
adapter.instantiateItem(viewPager, SIZE-1);
adapter.notifyDataSetChanged();
In getItem(), for the "position" create and return the new fragment (I used a switch statement here)
Update the getCount() method to return the new SIZE.
Let me know if you would like me to share the code.
I have an app with a ViewPager and three Fragments. I'm trying to figure out how to get the current Fragment being viewed so I can get at its arguments.
I have an OnPageChangeListener grabbing the current page index, but
ViewPager.getChildAt(int position);
returns a View. What's the relationship between this View and the current Fragment?
I finally found an answer that worked for me. Basically, you can access the fragment for a viewPager page by using the tag "android:switcher:"+R.id.viewpager+":0".
I've solved this problem the other way round.
Instead of searching for the fragment from the activity, I'm registering the Fragment during it's onAttach() method at it's owner activity and de-registering it in the onStop() method.
Basic Idea:
Fragment:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try{
mActivity = (IMyActivity)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString() +" must be a IMyActivity");
}
mActivity.addFragment(this);
}
#Override
public void onStop() {
mActivity.removeFragment(this);
super.onStop();
}
IMyActivity:
public interface IFriendActivity {
public void addFragment(Fragment f);
public void removeFragment(Fragment f);
}
MyActivity:
public class MyActivity implements IMyActivity{
[...]
#Override
public void addFragment(Fragment f) {
mFragments.add(f);
}
#Override
public void removeFragment(Fragment f) {
mFragments.remove(f);
}
}
Edit - Don't do this. If you're tempted to, read the comments for why it's a bad idea.
On the odd-chance you're still trying to solve this problem:
Extend FragmentPagerAdapter. In the constructor, build the Fragments you need and store them in a List (array/ArrayList) of Fragments.
private final int numItems = 3;
Fragment[] frags;
public SwipeAdapter (FragmentManager fm) {
super(fm);
//Instantiate the Fragments
frags = new Fragment[numItems];
Bundle args = new Bundle();
args.putString("arg1", "foo");
frags[0] = new MyFragment();
frags[1] = new YourFragment();
frags[2] = new OurFragment();
frags[2].setArguments(args);
}
Then for getItem(int position), you can do something like
public Fragment getItem(int position) {
return frags[position];
}
I'm not sure if this is the generally accepted way of doing it but it worked for me.
Edit
This is really not a good way to go. If you plan on handling orientation changes or your app going into the background, then this will probably break your code. Please read the comments below this answer for more info. Rather use #James 's answer
Yes, it's possible if you are using FragmentStatePagerAdapter.
ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
PLEASE DON'T USE THIS
Make your adapter extend the following FragmentStatePagerWithCurrentAdapter class and instead of implementing getItem implement the same code into getItemAtIndex
Set the ViewPager OnPageChangeListener, to the instance of the adapter.
When you need to access the current Fragment you just call adapter.getCurrentItem().
package your.package;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.SparseArray;
import android.view.ViewGroup;
public abstract class FragmentStatePagerWithCurrentAdapter
extends FragmentStatePagerAdapter
implements OnPageChangeListener {
int currentPage = 0;
private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();
public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public final Fragment getItem(int index) {
Fragment myFragment = getItemAtIndex(index);
mPageReferenceMap.put(index, myFragment);
return myFragment;
}
public abstract Fragment getItemAtIndex(int index);
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferenceMap.remove(Integer.valueOf(position));
}
public Fragment getCurrentItem() {
return mPageReferenceMap.get(currentPage);
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int newPageIndex) {
currentPage = newPageIndex;
}
}
I used as reference the following blog post: http://tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html
It's been explained here : http://developer.android.com/guide/topics/fundamentals/fragments.html
In OnCreateView you must return a view to draw a UI for your fragment, I think that's the relationship.
Also this question might be similar: Get focused View from ViewPager
You can do so:
- On the class extent of a view pager adapter (such as PagerAdapter , FragmentStatePagerAdapter...) override method instantiateItem :
#Override
public Object instantiateItem(ViewGroup container, int position) {
final Fragment frag = (Fragment) super.instantiateItem(container, position);
if(frag instanceof ListNoteOfTypeFragment){
final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag;
//do whatever you want with your fragment here
listNoteOfTypeFragment.setNoteChangeListener(mListener);
}
return frag;
}
Definitive answer that works seamlessly (but small hack):
somewhere in page fragment's layout:
<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="#+id/fragment_reference">
<View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>
</FrameLayout>
in fragment's onCreateView():
...
View root = inflater.inflate(R.layout.fragment_page, container, false);
ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference);
ref.setTag(this);
ref.getChildAt(0).setTag("fragment:" + pageIndex);
return root;
and method to return Fragment from ViewPager, if exists:
public Fragment getFragment(int pageIndex) {
View w = mViewPager.findViewWithTag("fragment:" + pageIndex);
if (w == null) return null;
View r = (View) w.getParent();
return (Fragment) r.getTag();
}
Jorge Garcia's FragmentStatePagerWithCurrentAdapter is a very good solution but it needs a minor improvement. In case the activity gets destroyed and re-created in response to a configuration change or something like that the getItem will not be called for the fragments that were saved and retrieved by the fragment manager. So I override getItem normally in my subclass and I put the following in the FragmentStatePagerWithCurrentAdapter
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object item = super.instantiateItem(container, position);
if ( item instanceof Fragment ) {
pageReferenceMap.put(position, (Fragment)item);
}
return item;
}
The instantiateItem is called every time the fragment in that position is accessed.
Or just save all Fragments in a map:
public class MyFragment extends Fragment implements OnPageChangeListener {
private ViewPager viewPager;
private FragmentStatePagerAdapter viewAdapter;
private View rootView;
private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.introdution, container, false);
viewPager = (ViewPager) rootView.findViewById(R.id.pager);
viewAdapter = new ViewAdapter(getFragmentManager());
viewPager.setAdapter(viewAdapter);
viewPager.addOnPageChangeListener(this);
return rootView;
}
private class ViewAdapter extends FragmentStatePagerAdapter {
public ViewAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
Fragment result = null;
switch (position) {
case 0: result = Fragment1.newInstance(); break;
case 1: result = Fragment2.newInstance(); break;
}
if (result != null)
fragments.put(position, result);
return result;
}
#Override
public int getCount() {
return 2;
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
Fragment currentFragment = fragments.get(position);
}
}
I think there is the better way by using this
Log.i(TAG, "getCurrentItem " + mViewPager.getCurrentItem());
Can get the current display fragment page.