Update Fragment ViewPager

How to Update Fragment ViewPager

My approach to update fragments within the viewpager is to use the setTag() method for any instantiated view in the instantiateItem() method. So when you want to change the data or invalidate the view that you need, you can call the findViewWithTag() method on the ViewPager to retrieve the previously instantiated view and modify/use it as you want without having to delete/create a new view each time you want to update some value.

Imagine for example that you have 100 pages with 100 TextViews and you only want to update one value periodically. With the approaches explained before, this means you are removing and instantiating 100 TextViews on each update. It does not make sense…

You can see complete code here

In my adapter

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;

import com.thedeveloperworldisyours.refreshcurrentfragment.fragments.FirstFragment;
import com.thedeveloperworldisyours.refreshcurrentfragment.fragments.SecondFragment;
import com.thedeveloperworldisyours.refreshcurrentfragment.fragments.ThirdFragment;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by javierg on 09/01/2017.
 */

public class MyPagerAdapter extends FragmentPagerAdapter {
    private static int NUM_ITEMS = 3;
    private Map<Integer, String> mFragmentTags;
    private FragmentManager mFragmentManager;

    public MyPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
        mFragmentManager = fragmentManager;
        mFragmentTags = new HashMap<Integer, String>();
    }

    // Returns total number of pages
    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    // Returns the fragment to display for that page
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return FirstFragment.newInstance();
            case 1:
                return SecondFragment.newInstance();
            case 2:
                return ThirdFragment.newInstance();
            default:
                return null;
        }
    }

    // Returns the page title for the top indicator
    @Override
    public CharSequence getPageTitle(int position) {
        return "Page " + position;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object object = super.instantiateItem(container, position);
        if (object instanceof Fragment) {
            Fragment fragment = (Fragment) object;
            String tag = fragment.getTag();
            mFragmentTags.put(position, tag);
        }
        return object;
    }

    public Fragment getFragment(int position) {
        Fragment fragment = null;
        String tag = mFragmentTags.get(position);
        if (tag != null) {
            fragment = mFragmentManager.findFragmentByTag(tag);
        }
        return fragment;
    }
}

And now in my activity:

import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.thedeveloperworldisyours.refreshcurrentfragment.adapter.MyPagerAdapter;

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{

    MyPagerAdapter mAdapterViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager viewPager = (ViewPager) findViewById(R.id.activity_main_view_pager);
        mAdapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(mAdapterViewPager);
        viewPager.addOnPageChangeListener(this);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {

        Fragment fragment = mAdapterViewPager.getFragment(position);
        if (fragment != null) {
            fragment.onResume();
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

Finally in your fragment, something like that:

import android.animation.Animator;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.thedeveloperworldisyours.refreshcurrentfragment.R;

public class FirstFragment extends Fragment {
    RelativeLayout mView;
    Context mContext;

    public FirstFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @return A new instance of fragment FirstFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static FirstFragment newInstance() {
        return new FirstFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_first, container, false);
        mView = (RelativeLayout) view.findViewById(R.id.fragment_first_view);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        onAnimationStart();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    public void onAnimationStart() {
        Log.d("FirstFragment","onAnimationStart()");

        // get the center for the clipping circle
        int cx = (mView.getRight());
        int cy = (mView.getBottom());

        // get the final radius for the clipping circle
        int finalRadius = Math.max(mView.getWidth(), mView.getHeight());

        // create the animator for this view (the start radius is zero)
        Animator anim =
                ViewAnimationUtils.createCircularReveal(mView, cx, cy, 0, finalRadius);
        anim.setDuration(1000);

        // make the view visible and start the animation
        mView.setVisibility(View.VISIBLE);
        anim.start();
    }

}

You can see complete code here

4 thoughts on “Update Fragment ViewPager

  1. Hello

    I am trying to fetch data dynamically in ViewPager. The application is a multi-question quiz, which can have different types of questions and any number of questions. These questions can be simple text options, image options, rating slider, number slider or open text. The problem is that
    1. I cannot set correct data in various fragments, meaning that rating slider either takes default values or may take min/max values of another question.
    2. Image options do not show
    3. Image placeholders show but scroller does not work.
    In short, I am stuck and cannot find a way out.
    Can you please help?

  2. I must say it was hard to find your website in google.
    You write great articles but you should rank your page higher in search engines.
    If you don’t know how to do it search on youtube: how
    to rank a website Marcel’s way

Leave a Reply

Your email address will not be published. Required fields are marked *