Reputation: 564
I am working on an application which has a ViewPager view in it, I have created a PagerAdapter, which has the view, instantiateItem() method of PagerAdapter is called twice in create() i don't know why, can anyone help me with this?
Here is my code,
View PagerView;
MyPagerAdapter adapter;
ViewPager pager;
adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
pager.setCurrentItem(0);
public class MyPagerAdapter extends PagerAdapter {
@Override
public Object instantiateItem(final View collection, final int position) {
Log.d("Inside", "Pager");
PagerView = new View(collection.getContext());
LayoutInflater inflater = (LayoutInflater) collection.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
PagerView = inflater.inflate(R.layout.tablemenu, null, false);
tbMenuDetails = (TableLayout) PagerView
.findViewById(R.id.Menutable1);
scrollview = (ScrollView) PagerView.findViewById(R.id.scrollView1);
tbMenuDetails.removeAllViews();
removeTableRows();
createTableLayout(position);
String str[][] = datasource.GetSubMenuDetailsFromMenuId(MenuIdlst
.get(position).trim());
Log.d("Str", "" + str.length);
for (int i = 0; i < str.length; i++) {
addRows(str[i][1], str[i][2], str[i][0], str[i][3], position);
Log.d("Message", "Pos " + position + " SubMenuName" + str[i][2]
+ " SubMenuId" + " " + str[i][0] + " TypeID" + " "
+ str[i][3]);
}
// View view = inflater.inflate(resId, null);
((ViewPager) collection).addView(PagerView, 0);
return PagerView;
}
@Override
public void destroyItem(final View arg0, final int arg1,
final Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
@Override
public boolean isViewFromObject(final View arg0, final Object arg1) {
return arg0 == ((View) arg1);
}
@Override
public void finishUpdate(View arg0) {
// TODO Auto-generated method stub
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
// TODO Auto-generated method stub
}
@Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
@Override
public void startUpdate(View arg0) {
// TODO Auto-generated method stub
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return MenuIdlst.size();
}
}
Please help
Upvotes: 10
Views: 13292
Reputation: 269
There change to make that is essential for the isViewFromObject() method. It is very important and in it's documentation it is said that "This method is required for a PagerAdapter to function properly."
@Override
public boolean isViewFromObject(View view, Object object) {
if(object != null){
return ((Fragment)object).getView() == view;
}else{
return false;
}
}
You can look here.
Upvotes: -1
Reputation: 5271
Use fragments for each view in a pager.
write the below code in onCreate()
method of the FragmentActivity
.
List<Fragment> fragments = new Vector<Fragment>();
//for each fragment you want to add to the pager
Bundle page = new Bundle();
page.putString("url", url);
fragments.add(Fragment.instantiate(this,MyFragment.class.getName(),page));
//after adding all the fragments write the below lines
this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
mPager.setAdapter(this.mPagerAdapter);
A sample fragment definition:
public class MyFragment extends Fragment {
public static MyFragment newInstance(String imageUrl) {
final MyFragment mf = new MyFragment ();
final Bundle args = new Bundle();
args.putString("somedata", "somedata");
mf.setArguments(args);
return mf;
}
public MyFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String data = getArguments().getString("somedata");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate and locate the main ImageView
final View v = inflater.inflate(R.layout.my_fragment_view, container, false);
//...
return v;
}
I follow this method whenever i need to use ViewPager
. Hope this helps. I couldn't figure out why your instantiate method was being called twice from the information you have provided.
Upvotes: 2
Reputation: 21883
ViewPager.setOffscreenpageLimit(int) has a minimum value of 1. You can see this from the source code for ViewPager:
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
...
/**
* Set the number of pages that should be retained to either side of the
* current page in the view hierarchy in an idle state. Pages beyond this
* limit will be recreated from the adapter when needed.
*
* <p>This is offered as an optimization. If you know in advance the number
* of pages you will need to support or have lazy-loading mechanisms in place
* on your pages, tweaking this setting can have benefits in perceived smoothness
* of paging animations and interaction. If you have a small number of pages (3-4)
* that you can keep active all at once, less time will be spent in layout for
* newly created view subtrees as the user pages back and forth.</p>
*
* <p>You should keep this limit low, especially if your pages have complex layouts.
* This setting defaults to 1.</p>
*
* @param limit How many pages will be kept offscreen in an idle state.
*/
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
You should see a warning in Logcat if you try to set it to zero.
The lower limit is 1 for a very good reason. The adjacent page needs to be already loaded when you scroll the pager - otherwise you will not see anything for the next page. If you manage to force the offscreen page limit to zero, you would probably just see a black, empty page as you scroll from the first page to the second. If you have a particular problem with both the first and second pages being created at the beginning, then try to target and fix that.
Upvotes: 3
Reputation: 12596
If you decide to use Fragments, don't implement PagerAdapter
. Instead, extend FragmentPagerAdapter
or FragmentStatePagerAdapter
:
private class MyPagerAdapter extends FragmentStatePagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return NUMBER_OF_PAGES_IN_PAGER;
}
@Override
public Fragment getItem(int position) {
// Implement the static method newInstance in MyFragment.java yourself.
// It should return you a brand new instance of MyFragment, basically using
// the code you had in your original instantiateItem method.
return MyFragment.newInstance(position, ... etc ...);
}
}
Then in your Activity:
myPagerAdapter = new MyPagerAdapter(getFragmentManager());
// or myPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
myViewPager.setAdapter(myPagerAdapter);
To get more info on how to use Fragments and ViewPagers: https://developer.android.com/reference/android/app/Fragment.html https://developer.android.com/reference/android/support/v4/view/ViewPager.html https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
Upvotes: 6
Reputation: 741
ViewPager by default preloads one page ahead / before the current page (if any). You didn't say if it's being called for the same or different position.
Upvotes: 4