i working viewpager.i have 4 fragments and add there fragments in viepager.but i want to add fragments dinamically
Here is my adapter
public class MyPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fragments = new ArrayList<Fragment>();
for (int i = 0; i < 10; i++) {
fragments.add(new FragmentBlue());
}
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
}
And here is the activity
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyPagerAdapter pageAdapter = new MyPagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager)findViewById(R.id.myViewPager);
pager.setAdapter(pageAdapter);
}
}
how i can add fragments dynamically instead of static GetCountSize(). for more information, i want to add 10 fragments in viewpager and each fragments background wast be different.
Consider using ViewPager2. By design it allows to modify fragments collection. You can find code sample here.
By using FragmentPagerAdapter we can not achieve infinite pager view
functionality.For this I have written my own pager view .Here every
time when you swipe the page it will ask for next page /previous page
by passing current page as reference.So by writing your own logic in
getNextPage(PageView currentPage)/getPreviousPage(PageView
currentPage) methods you can return the respective page until it reaches end.if
reaches end simply return null in those methods.
Here you can fine that sample project.
Let me know if you face any problem while using it.
Related
I am creating an app that is using a viewpager to slide between 4 specific fragments.
All the examples of viewpager I have read so far, create new fragments each time the getPosition method of FragmentPagerAdapter is called. So it's something like:
return FragmentA.newInstance();
What I have done is the following:
In the main activity
public static final int FRAGMENTS = 4;
public static final String FRAGMENT_LIST ="LIST";
public static final String FRAGMENT_SETTINGS = "SETTINGS";
public static final String FRAGMENT_MAP = "MAP";
public static final String FRAGMENT_TICKET = "TICKET";
MainAdapter _adapter;
ViewPager _pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(new FragmentMap(), FRAGMENT_MAP)
.add(new FragmentList(), FRAGMENT_LIST)
.add(new FragmentTicket(), FRAGMENT_TICKET)
.add(new FragmentSettings(), FRAGMENT_SETTINGS)
.commit();
}
_adapter = new MainAdapter(getSupportFragmentManager());
_pager = (ViewPager) findViewById(R.id.pager);
_pager.setAdapter(_adapter);
}
and in the adapter:
public class MainAdapter extends FragmentPagerAdapter {
FragmentManager _manager;
public MainAdapter(FragmentManager fm) {
super(fm);
_manager = fm;
}
#Override
public Fragment getItem(int position) {
return _manager.getFragments().get(position);
}
#Override
public int getCount() {
return ActivityMain.FRAGMENTS;
}
}
This raises an exception because the adapter is trying to change the tag of each fragment in getItem
My questions are:
a) Is it incorrect to always use the same fragment every time? I have seen no example that uses the above method or a similar one, they always create a new instance in the getItem method
b) If I wish for fragments to have some persistence, then does that mean that I should store the data that should be held by each fragment in static variables and always create new instances that use those variables?
a) You must create a new instance in the getItem() method, this method is not called every time you switch fragment from your viewpager.
I recommend you to use your adapter like
public class MainAdapter extends FragmentPagerAdapter {
public MainAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
case 0 :
return new FragmentMap();
case 1 :
return new FragmentList();
case 2 :
return new FragmentTicket();
case 3 :
return new FragmentSettings();
default :
return null;
}
#Override
public int getCount() {
return ActivityMain.FRAGMENTS;
}
}
b) Fragments in FragmentPagerAdapter are persistents, and they will be recreate only if you switch several fragment in your ViewPager. You can set the refresh limit by _pager.setOffscreenPageLimit(3); for exemple if you never want to recreate your fragments in your case.
For more information : http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
a) I think it's perfectly ok. They always create ne instance because it is easier and in many cases (like image gallery) it is better.
b) Static variables get lost if you send the app to backround and then return to it. Shared prefferences or bundle should do the work.
You should use FragmentStatePagerAdapter. If you fragmentstatepager adapter, you can remove or add fragment dynamically.
I have implemented view pager using the FragmentStatePagerAdapter. I have used 3 fragments in the view. The view pager is showing all 3 tabs with views as it should be , now my issue is that the third fragment is not visible but i am able to scroll till third tab and when i scroll back i see the second fragment but again the first fragment vanishes and all i am left is with second fragment.
mPager = (ViewPager)mContext.findViewById(R.id.viewPager);
mPager.setOnPageChangeListener(this);
mPagerAdapter = new MyPagerAdapter(mContext.getSupportFragmentManager(),mContext);
mPager.setAdapter(mPagerAdapter);
adapter code is
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private int NUM_PAGES = 3;
List<Fragment> listFragment = new ArrayList<Fragment>();
private MyActivity mContext;
public MyPagerAdapter(FragmentManager fragmentManager, MyActivity mActivity) {
super(fragmentManager);
this.mContext = mActivity;
listFragment.add(new FirstFragment());
listFragment.add(new SecondFragment());
listFragment.add(new ThirdFragment());
}
#Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
Log.v("fragment position",""+position);
return listFragment.get(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
I am stuck in this for a while, i would really appreciate some help.Thank you.
It is advised to use FragmentPagerAdapter instead of FragmentStatePagerAdapter, because of very nature of those two. FragmentStatePagerAdapter is being that is able to scroll through infinite views. In case of fixed amount of them, like your case you should use FragmentPagerAdapter.
If you happen to have context issues later override following method:
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mFragments.remove(position);
mFragments.add(position, fragment);
return fragment;
}
Where mFragments is your list.
I've got a FragmentActivity when I instantiate three different (n, n+1, n+2) Fragments.
I need to keep each Fragment updated when user swipes to it, so I used ViewPager.SimpleOnPageChangeListener.onPageSelected in the Fragment Activity, so when user swipes to n+1 or n+2 Fragment and again to n that function update the content.
Without using this workaround if I'm in the Fragment n+1, both n and n+2 are already loaded! I'd like instead that the Fragment load when the user swipes to it, without "pre-load".
This workaround works fine for me but it has a problem: the n Fragment that is the first in the list at start up of the app doesn't load its content. To load its content I have to swipe to n+1 then go back to n.
I know that the content of the Fragment should be setted on the class called at the moment of instantiate the fragment and that extends Fragment class, but in this way I don't know how to keep up to date each Fragment, as I do using onPageSelected.
Any suggestions?
EDIT 1:
I istantiate my fragments in this way in onCreate():
for(int x = 0; x < 3; x++) {
Bundle b = new Bundle();
b.putString( "id" , x );
Fragment myFrag = Fragment.instantiate( myContext , Mm_FragmentPage.class.getName() );
myFrag.setArguments( b );
fragments.add(myFrag);
}
Then I set the adapter in the ViewPager:
mPagerAdapter = new PagerAdapter( super.getSupportFragmentManager() , fragments );
mPager.setAdapter( mPagerAdapter );
Then I use the adapter in the TitlePageIndicator
titleIndicator = (TitlePageIndicator) findViewById( R.id.titleFragments );
titleIndicator.setViewPager( mPager );
titleIndicator.setOnPageChangeListener( new myPageChangeListener() );
And, at the end, the class PagerAdapter:
public class PagerAdapter extends FragmentPagerAdapter
{
// fragments to instantiate in the viewpager
private List<Fragment> fragments;
// constructor
public PagerAdapter(FragmentManager fm, List<Fragment> fragments)
{
super(fm);
this.fragments = fragments;
}
// return access to fragment from position, required override
#Override
public Fragment getItem(int position)
{
return this.fragments.get(position);
}
// number of fragments in list, required override
#Override
public int getCount()
{
return this.fragments.size();
}
#Override
public CharSequence getPageTitle(int position)
{
return getResources().getStringArray( R.array.tab_header_name )[ position ];
}
}
OK, so first thing you need to set OnPageChangeListener on the ViewPager and implement method onPageSelected(int i) and call the adapter's notifyDataSetChanged(), like so:
mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i2) {
}
#Override
public void onPageSelected(int i) {
//Tell the adapter that the content was changed
mPager.getAdapter().notifyDataSetChanged();
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
In order to keep the fragments updated, you need to extends FragmentStatePagerAdapter and not FragmentPagerAdapter like what you did. The difference is that with FragmentPagerAdapter the ViewPager will never re-create the fragments, while in FragmentStatePagerAdapter it will.
Then on getItem(..) make sure to return a new instance of the fragment with the new content by passing the content to its arguments via setArguments(). Then override also getItemPosition(..) to tell the adapter that the fragment is not found, and therefore it must re-create it.
public class MyPagerAdapter extends FragmentStatePagerAdapter {
//List to hold the fragments to be shown
//NOTE: It's a list of Fragment classes, not a list of Fragment instances!
private List<Class<? extends Fragment> fragments;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
fragments.add(SomeFragment.class);
fragments.add(AnotherFragment.class);
fragments.add(MoreFragment.class);
}
#Override
public Fragment getItem(int i) {
try {
//Creates a new instance of the fragment
Fragment instance = fragments.get(i).newInstance();
//Put the new content by passing Bundle with new content
instance.setArguments(args);
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
#Override
public int getItemPosition(Object object) {
//NOTE: you might want to put better logic here
return POSITION_NONE;
}
#Override
public int getCount() {
return pages.size();
}
}
Every time you slide from one fragment to another, onPageSelected() will be fired calling notifyDataSetChanged() which will force the adapter to check also if the position of the fragment has changed. Since we return POSITION_NONE in getItemPosition(..), the adapter thinks that the position changed and will then call getItem(i). In getItem(i) we return a new instance (optionally, passing new arguments). Problem solved! :)
I just tested it by myself, created a small app that have a counter which increases everytime the user slides the page and it works!
This way you can drop the ViewPager.SimpleOnPageChangeListener.onPageSelected.
Learn more about ViewPager.
I'm new to Android developing and I would really appreciate some help here.
I'm using a fragment that contains a TextView and I'm using 5 instances of the same MyFragment class.
In the activity, i got a button and a ViewPager, and I need the button to update all the fragment instances content, whenever its clicked.
Here's the Activity
public class MainActivity extends FragmentActivity {
final static String[] CONTENT = {"a", "b"};
ViewPager pager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<MyFragment> fragments = new Vector<MyFragment>();
for(int i = 0; i < 5; i++){
MyFragment fragment = new MyFragment(CONTENT);
fragments.add(fragment);
}
PagerAdapter adapter = new PagerAdapter(this.getSupportFragmentManager(), fragments);
pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(adapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//method that isn't working
PagerAdapter adapter = (PagerAdapter)pager.getAdapter();
for(int i = 0; i < 5; i++){
MyFragment fragment = (MyFragment) adapter.getItem(i);
fragment.textView.setText(fragment.content[1]);
}
}
});
}
}
The Fragment
public class MyFragment extends Fragment{
String[] content;
TextView textView;
public MyFragment(String[] content) {
this.content = content;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, container, false);
textView = (TextView) view.findViewById(R.id.textView1);
textView.setText(content[0]);
return view;
}
}
And the FragmentPagerAdapter
public class PagerAdapter extends FragmentPagerAdapter{
List<MyFragment> fragments;
public PagerAdapter(FragmentManager fm, List<MyFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);
}
#Override
public int getCount() {
return fragments.size();
}
}
The OnClick method gives me a NullPointerException whenever i try to access a fragment from the adapter which is less than adapter.getCurrentItem() - 1, or more than adapter.getCurrentItem() + 1.
Any idea on how to update all the fragments at the same time?
Thanks in advance.
The easiest way to update those fragments is to use your code and set the number of fragments that the ViewPager holds in memory to the number of total fragments - 1(so all fragments are valid no matter at what page you are). In your case:
pager.setOffscreenPageLimit(4); // you have 5 elements
You can still use the method from my comment with the method onPageScrollStateChanged(so the update will start the moment the user starts swiping) to see when the user is starting to swipe the pager and update the fragments to the left and right of the currently visible fragment, but this will be a bit difficult to get right so I recommend to go with the first option.
Some points regarding your code containing fragments:
If you nest the fragment class make it static so you don't tie it to the activity object.
Don't create a constructor for a Fragment besides the default one. If the framework needs to recreate the fragment it will call the default constructor and if it is not available it will throw an exception. For example, try to change the orientation of the phone/emulator and see what happens(this is one of the cases when Android will recreate the fragments). Last, use a custom name for the ViewPager's adapter, you use PagerAdapter which is the name of the super class of FragmentViewPager and it's very confusing for someone reading your code.
If you need to pass data to the Fragment you could use a creation method like the one below:
public static MyFragment newInstance(String text) {
MyFragment f = new MyFragment();
Bundle b = new Bundle();
b.putString("content", text);
f.setArguments(b);
return f;
}
The text will be available in MyFragment by using getArguments().getString("content");
I have this problem as you can see in the pictures below:
1) http://imageshack.us/photo/my-images/19/schermata20120512a09444.png/
2) http://imageshack.us/photo/my-images/651/schermata20120512a09444.png/
I have done one viewpager with three fragment , but when scroll, I see one of them, i would see two fragments.
my cose is:
public class FragmentProjetSwipePageActivity extends FragmentActivity {
// derived from http://thepseudocoder.wordpress.com/2011/10/05/android-page-swiping-using-viewpager/
// list contains fragments to instantiate in the viewpager
List<Fragment> fragmentsV1 = new Vector<Fragment>();
// page adapter between fragment list and view pager
private PagerAdapter mPagerAdapter;
// view pager
private ViewPager mPager;
// activity data
public String p2text,p3text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// creating fragments and adding to list
fragmentsV1.add(Fragment.instantiate(this,Page1Fragment.class.getName()));
fragmentsV1.add(Fragment.instantiate(this,Page2Fragment.class.getName()));
fragmentsV1.add(Fragment.instantiate(this,Page3Fragment.class.getName()));
// creating adapter and linking to view pager
mPager = (ViewPager) super.findViewById(R.id.pager1);
this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(),fragmentsV1,this );
mPager.setAdapter(this.mPagerAdapter);
//Set a listener that will be invoked whenever the page changes or is incrementally scrolled.
}
}
PagerAdapter.java
public class PagerAdapter extends FragmentPagerAdapter {
// fragments to instantiate in the viewpager
private List<Fragment> fragments;
FragmentManager fm;
private static int NUM_PAGER_VIEWS = 2;
Context contex;
// constructor
public PagerAdapter(FragmentManager _fm,List<Fragment> fragments) {
super(_fm);
this.fragments = fragments;
fm=_fm;
}
// return access to fragment from position, required override
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
// number of fragments in list, required override
#Override
public int getCount() {
return NUM_PAGER_VIEWS;
//return this.fragments.size();
}
}
thanks