25

In My application, I have used the ViewPager. Like,

(say main.xml)

<android.support.v4.view.ViewPager
     android:id="@+id/viewPager"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:layout_above="@+id/register_header" />

And Create ViewPager object and ViewPagerAdapter(which extends FragmentPagerAdapter) object in FragmentActivity.

_mViewPager = (ViewPager) findViewById(R.id.viewPager);

_adapter = new ViewPagerAdapter(getApplicationContext(),
         getSupportFragmentManager());

_mViewPager.setAdapter(_adapter);

And the Adapter class is like,

public class ViewPagerAdapter extends FragmentPagerAdapter {
    private Context _context;
    private FragmentManager manager;
    private Fragment f;
    private String classname="ViewPagerAdapter";
    public ViewPagerAdapter(Context context, FragmentManager fm) {
        super(fm);  
        _context=context;
        manager=fm;
        }
    @Override
    public Fragment getItem(int position) {
        Log.i(classname,"getItem called"+position);
        f = new Fragment();
        f=MyFragment.newInstance();
        Bundle args = new Bundle();
        args.putInt("position", position);
        f.setArguments(args);
        return f;
    }

    @Override
    public int getCount() {
        return User.getPageCount();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

And in MyFragment Class,

In onResume , I have to store the wigets object to the common static variable.

public void onResume() {
        super.onResume();
        pageIndex = getArguments().getInt("position");      
        User.useTextview1=textview1;
        User.useTextview2= textview2;
        User.current_pageIndex=pageIndex;



    }

I have to update the textviews got from the User class in the FragmentActivity. My Problem is getItem() method is called twice on First time In Fact , the view displayed in the emulator is 0th index, but got 1st Index value in the FragmentActivity. If I stopped the calling of getItem() method on second time, I can able to get the 0th index TextView reference in the FragmentActivity.

Please provide me the best way to do this.

Thanks

Sridhar
  • 2,228
  • 10
  • 48
  • 79

5 Answers5

19

The FragmentPagerAdapter instantiates 2 Fragments on start, for index 0 and for index 1. If you want to get data from the Fragment which is on the screen, you can use setOnPageChangeListener for the Pager to get current position. Then have SparseArray with WeakReference to your fragments. Update that array in the getItem call. When onPageSelected gets called use that position to get reference to right Fragment and update User data.

Initialization of array:

private SparseArray<WeakReference<MyFragment>> mFragments = new SparseArray<WeakReference<MyFragment>>(3);
Niko
  • 8,093
  • 5
  • 49
  • 85
  • It is an array which maps objects for certain position. In getItem you use it this way: myMemberSparseArrayObject.put(position, new WeakReference (f)); – Niko Mar 05 '13 at 08:36
  • ok, so FragmentActivity will maintain the myMemberSparseArrayObject Right? – Sridhar Mar 05 '13 at 08:38
  • ,How to initialize myMemberSparseArrayObject? – Sridhar Mar 05 '13 at 08:48
  • see my answer how to initialize array, the 3 is max value it can hold references because thats the normal number of Fragments alive with Pager – Niko Mar 05 '13 at 09:14
  • @Niko http://stackoverflow.com/q/18097567/1503130 I got stuck with an issue can you have a look at this – Prateek Aug 07 '13 at 08:41
  • @Niko Hello, I don't really understand u how u use `SparseArray` exactly? Would u like to update new answer with more detail, about the coding .etc. – Huy Tower Apr 11 '14 at 11:17
2

in getItem method i wrote this..

@Override
public Fragment getItem(int index) {
    EditFragment frag = new EditFragment();
    Bundle args = new Bundle();
    args.putSerializable("currentItem", itemsList.get(index));
    frag.setArguments(args);
    return (frag);
}

here itemsList.get(index) is the model class object which i will use in EditFragment class. here is that.

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    View result = inflater.inflate(R.layout.pager_fragment_layout, container, false);
    image = (ImageView)result.findViewById(R.id.pager_image);
    text = (TextView)result.findViewById(R.id.pager_item_desc);
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity()).build();
    ImageLoader.getInstance().init(config);
    imLoader = ImageLoader.getInstance();

            ****NOTE
    final SwapItems itemList = (SwapItems) getArguments().getSerializable("currentItem");

    imagePath = itemList.getPaths().get(0);
    imLoader.displayImage(imagePath,image);
    text.setText(itemList.getItemDescription());

    image.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Fragment fragment = new ItemImagesFragment();
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            Bundle bundle = new Bundle();
            bundle.putSerializable("val", itemList);
            fragment.setArguments(bundle);
            fragmentTransaction.replace(R.id.content_frame, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    });
    return result;
}

NOTE: here i am getting swapitems model object from previous getItem method is 'final'. this solves my issue. Earlier i was initialized the same object with static as modifier.

hope yours will also clear

GvSharma
  • 2,632
  • 1
  • 24
  • 30
1

My Problem is getItem() method is called twice on First time

This is not the problem, this is default feature of FragmentPagerAdapter. Its good for you to swipe from this page to the next one and previous one.

the view displayed in the emulator is 0th index, but got 1st Index value in the FragmentActivity

I got the same issue, and I know why. This because you used same Fragment in View Pager.

How to fix this is separate Fragments by using different Fragment.

Huy Tower
  • 7,769
  • 16
  • 61
  • 86
  • i implemented this...inside i need click on each page and which will go to other fragment...but it is giving by default wrong positions ... i understand you answer to some extent.. can you explain with some more clarity – GvSharma Apr 21 '14 at 14:59
  • It looks like u got another issue `it is giving by default wrong positions`. You can use `viewpager.getCurrentItem(position)` to indicate which page need go to after clicked some buttons. – Huy Tower Apr 22 '14 at 01:51
  • @GVSharma What solution you got ? and which solution you have applied – sam_k Jun 13 '14 at 07:46
  • @GVSharma did you resolve the problem i am facing the same problem public Fragment getItem(int i) call twice which give the wrong position i have 5 tabs with 5 fragments if(i>0){ i = i-1; } work but the problem is that last tab or fragment not been calling b/c position = position -1 – Mushtaq Rahim Oct 09 '18 at 10:51
1

I faced the same issue - getItem() method was called twice. I don't know about your purposes of using that method by mine was to trigger changes in a hosting activity when new slide appears.

Well, first of all getItem() is not a right method to get event of appearing new slide.

I used ViewPager.OnPageChangeListener listener on ViewPager itself for this purpose. Here is what I did:

In Activity that holds slide fragments:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.signature_wizard_activity);

    // Instantiate a ViewPager and a PagerAdapter.
    mPager = (ViewPager) findViewById(R.id.pager);
    mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
    mPager.setAdapter(mPagerAdapter);
    mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            onSlideChanged(position); // change color of the dots
        }
        @Override
        public void onPageSelected(int position) {}
        @Override
        public void onPageScrollStateChanged(int state) {}
    });
}

onPageScrolled() is called every time your slide appears, as a parameter it gets current position of the slide that is shown. Nice thing is that it is called including the first time it appears, not just when slide was changed.

When it can be used? For example if you have some wizard activity with ViewPager where you slide fragments with some hints, you probable would like to have a bar with grey dots below the slider that would represent the number of slides in total, and one of the dots will be different color representing the current slide. In this case ViewPager.OnPageChangeListener and method onPageScrolled() will be the best option.

Or if you have buttons PREV. and NEXT which change slides and you want to disable PREV. button on the first slide and disable NEXT button on the last slide. Here is how you do it inside onPageScrolled() method:

 @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if(position == 0){
                prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
                prevBtn.setEnabled(false);
            }else{
                prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
                prevBtn.setEnabled(true);
            }

            if(position == NUM_PAGES -1){
                nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
                nextBtn.setEnabled(false);
            }else{
                nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
                nextBtn.setEnabled(true);
            }
        }

where NUM_PAGES is a constant with total number of slides

Kirill Karmazin
  • 6,256
  • 2
  • 54
  • 42
0

you can use this method to update your views

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {
        // Fetch data or something...
    }
}
fawaad
  • 341
  • 6
  • 12
saurabh dixit
  • 863
  • 6
  • 19