View pager does not inflate the good page - android

I'm trying to use a view pager to make a gallery. Nevertheless it's always the view at the position 1 which is updated whereas i'm trying to update the current page (0 by default).
First of all i have created a view which gonna be inflated by the pager. This view is composed of 4 ImageView and 4 textview.
Then i created a adapter for the pager :
public class LivePagerAdapter extends PagerAdapter {
private CameraList cameras = null;
public LivePagerAdapter(CameraList cams)
{
this.cameras = cams;
}
#Override
public int getCount() {
return this.cameras.size() /4; // 4 imageview in a page
}
public void setCameras(CameraList cams)
{
this.cameras = cams;
}
#Override
public Object instantiateItem(View container, int position) {
LayoutInflater inflater = LayoutInflater.from(container.getContext());
View view = inflater.inflate(R.layout.pager,null);
((ViewPager) container).addView(view,0);
return view;
}
}
Finally in my activity i'm instanciate the pager like this :
adapter = new LivePagerAdapter(this.listeCamera);
pager = (ViewPager) findViewById(R.id.camspager);
pager.setAdapter(adapter);
pager.setCurrentItem(0);
After that i'm initialising a array with my 4 imageview :
tabImageView.add((ImageView) findViewById(R.id.cam1)); //Imageview located in the view loaded by the pager
tabImageView.add((ImageView) findViewById(R.id.cam2));
tabImageView.add((ImageView) findViewById(R.id.cam3));
tabImageView.add((ImageView) findViewById(R.id.cam4));
And when needed i add a image in the imageview.
It seems to works except that i'm asking the pager to start at position 0 and this is the view from position 1 which is updated with my images.
When i use findViewById(somethingInflatedByThePager) i need it to be the current page , how can i do that ?

What happens if you replace ((ViewPager) container).addView(view,0); by ((ViewPager) container).addView(view);

Related

RemoveView Function On ViewPager Not Working

I'm trying to remove a view from a Container of type ViewGroup like below, and I cast it into a ViewPager, but I noticed that the removeView() function is not working, as at now, I'm not sure of what I'm doing wrong.
I need help.
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
ViewPager viewPager = (ViewPager)container;
View view = (View)object;
ViewPager.removeView(view); //removeView is not working
layoutInflater = (LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View view=layoutInflater.inflate(R.layout.custom_layout,null);
ImageView imageView = (ImageView) view.findViewById(R.id.myImageView);
imageView.setImageResource(images[position]);
ViewPager viewPager = (ViewPager)container;
ViewPager.addView(view);
return view;
Yeah. It is works as expected. Instead of doing above, you need to remove the item for the ViewPager adapter. Something like below.
// Delete a page at a `position`
public void deletePage(int position) {
// Remove the corresponding item in the data set
pageIndexes.remove(position);
// Notify the adapter that the data set is changed
notifyDataSetChanged();
}

Issue with the Dynamic ViewPager -> Second layout not attahced

I am creating dynamic ViewPager as below : pls. check :
/** adding gridView created to main root layout.*/
pager=new ViewPager(this);
pagerAdapter = new KeyboardPagerAdapter();
pagerAdapter.addView (mGridImages, 0);
pagerAdapter.addView (mGridTextImages, 1);
pager.setAdapter (pagerAdapter);
ViewGroup.LayoutParams params = mGridImages.getLayoutParams();
params.height = mDeviceHeight;
pager.setLayoutParams(params);
linRootLayout.addView(pager);
return linRootLayout;
My Class KeyboardPagerAdapter is as below :
public class KeyboardPagerAdapter extends PagerAdapter{
// This holds all the currently displayable views, in order from left to right.
private ArrayList<View> views = new ArrayList<View>();
//-----------------------------------------------------------------------------
// Used by ViewPager. "Object" represents the page; tell the ViewPager where the
// page should be displayed, from left-to-right. If the page no longer exists,
// return POSITION_NONE.
#Override
public int getItemPosition (Object object)
{
int index = views.indexOf (object);
if (index == -1)
return POSITION_NONE;
else
return index;
}
// Used by ViewPager. Called when ViewPager needs a page to display; it is our job
// to add the page to the container, which is normally the ViewPager itself. Since
// all our pages are persistent, we simply retrieve it from our "views" ArrayList.
#Override
public Object instantiateItem (ViewGroup container, int position)
{
View v = views.get (position);
container.addView (v);
return v;
}
// Used by ViewPager. Called when ViewPager no longer needs a page to display; it
// is our job to remove the page from the container, which is normally the
// ViewPager itself. Since all our pages are persistent, we do nothing to the
// contents of our "views" ArrayList.
#Override
public void destroyItem (ViewGroup container, int position, Object object)
{
container.removeView (views.get (position));
}
// Used by ViewPager; can be used by app as well.
// Returns the total number of pages that the ViewPage can display. This must
// never be 0.
#Override
public int getCount ()
{
return views.size();
}
// Used by ViewPager.
#Override
public boolean isViewFromObject (View view, Object object)
{
return view == object;
}
// Add "view" to right end of "views".
// Returns the position of the new view.
// The app should call this to add pages; not used by ViewPager.
public int addView (View v)
{
return addView (v, views.size());
}
//-----------------------------------------------------------------------------
// Add "view" at "position" to "views".
// Returns position of new view.
// The app should call this to add pages; not used by ViewPager.
public int addView (View v, int position)
{
views.add (position, v);
return position;
}
//-----------------------------------------------------------------------------
// Removes "view" from "views".
// Retuns position of removed view.
// The app should call this to remove pages; not used by ViewPager.
public int removeView (ViewPager pager, View v)
{
return removeView (pager, views.indexOf (v));
}
//-----------------------------------------------------------------------------
// Removes the "view" at "position" from "views".
// Retuns position of removed view.
// The app should call this to remove pages; not used by ViewPager.
public int removeView (ViewPager pager, int position)
{
// ViewPager doesn't have a delete method; the closest is to set the adapter
// again. When doing so, it deletes all its views. Then we can delete the view
// from from the adapter and finally set the adapter to the pager again. Note
// that we set the adapter to null before removing the view from "views" - that's
// because while ViewPager deletes all its views, it will call destroyItem which
// will in turn cause a null pointer ref.
pager.setAdapter (null);
views.remove (position);
pager.setAdapter (this);
return position;
}
//-----------------------------------------------------------------------------
// Returns the "view" at "position".
// The app should call this to retrieve a view; not used by ViewPager.
public View getView (int position)
{
return views.get (position);
}
}
My issue is that, When I launch my app, The first page inside is displayed ok. But, Second pager is displayed as blank : white page.
What might be the issue ? Why PagerAdapter not taking second view as i have done as
pagerAdapter.addView (mGridImages, 0);
pagerAdapter.addView (mGridTextImages, 1);
1 > to add second view.
Pls. check and guide me.
Thanks.
Its my mystake. As Global I have setted the Visibility of my second layout to invisible.

Android: call adapter directly in viewpager or call fragment per page?

this question is related with this one that I asked before.
I create a viewpager in MainActivity.java like this:
final ViewPager viewPager = (ViewPager) findViewById(R.id.vp_horizontal_ntb);
viewPager.setAdapter(new PagerAdapter() {
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(final View view, final Object object) {
return view.equals(object);
}
#Override
public void destroyItem(final ViewGroup container, final int position, final Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public Object instantiateItem(final ViewGroup container, final int position) {
if(position==0) {
// here is important!
} else if(position == 1) {
}
...
}
});
Now I want fill each page with some json RecyclerView data list.(get json from network).
each page has independent data list.
For first time, I create a fragment for each page like this:
if (position == 0) {
final View view = LayoutInflater.from(getActivity().getBaseContext()).inflate(R.layout.fragment_tab0, null, false);
tabFragment.MyAdapter adapter = new tabFragment.MyAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new tab0Fragment(), getResources().getString(R.string.tab0));
container.addView(view);
return view;
}
(so for 5 page, I have 5 fragment.
DEMO
But My application run slow (laggy) when I swipe pages.(with tap buttom is normal)
So I tried write an Adapter class directly for each page like this:
if (position == 0) {
final View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.item_vp_list, null, false));
final RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getBaseContext(), LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new Tab0RecycleAdapter());
container.addView(view);
return view;
}
with top code,my application run fast again with swap pages!
Is it important to create fragment per each page?
why I must use fragment?(because some programmer recommended it in viewpager)
my method (second method without fragment) is true or false for a real application?
(I am noob and this is my first app)
Now I want fill each page with some json RecyclerView data list.(get json from network).
If you perform this network task on the UI thread, it will block and could cause laggy performance. This could be the reason your pages load slowly. You should perform network tasks on a separate thread.
So I tried write an Adapter class directly for each page like this
You only need one adapter per recycler view. If you want to support multiple views within the same adapter, override getItemViewType(). Example here: https://stackoverflow.com/a/26245463/7395923
Is it important to create fragment per each page?
Why I must use fragment? (because some programmer recommended it in view pager)
It is possible to use a view pager without fragments. Base on your previous question (linked at the top), it does seem overkill to load an entire fragment just to inflate a view. Here is a link to an example of a view pager without fragments: https://stackoverflow.com/a/18710626/7395923
I hope this helps.

PagerAdapter using fragments

Below is an example of a PagerAdapter.
Is it possible to get fragments and add these to the container instead of writing all logic in instantiateItem ?
Thanks in advance
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view=null;
if(position%2==0){
view = activity.getLayoutInflater().inflate(R.layout.pager_item,container, false);
}else{
view = activity.getLayoutInflater().inflate(R.layout.pager_item,container, false);
}
// Add the newly created View to the ViewPager
container.addView(view);
// Retrieve a TextView from the inflated View, and update it's text
TextView title = (TextView) view.findViewById(R.id.item_title);
title.setText(tabs[position]);
// Return the View
return view;
}
Use either FragmentPagerAdapter (for low amount of pages which will be kept in memory) or FragmentStatePagerAdapter (for high amount of pages which will be saved if too far from current screen). You need only override getCount() and getItem(int position) which is supposed to return a new fragment instance based on position.
Docs as well as usage examples:
http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html

destroyItem being called when position ==2 why? android pagerAdapter

I have a very simple PagerAdapter that for some reason, removes the views at position 0 and
1 when it is scrolled to position 2.
Specifically, when I first run the app, there are 3 views. I scroll to position 2 and position 1's view will disappear. View 0 is still there. If I scroll to view 0 and back to view 2 and again back to view 0, View 0 suddenly disappears. I do the same again, and I can actually see view 0 being instantiated and immediately destroyed.
what is going on here?
Main Activity
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyPagerAdapter adapter = new MyPagerAdapter(this);
final ViewPager myPager = (ViewPager) findViewById(R.id.mypanelpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(1);
}
public class MyPagerAdapter extends PagerAdapter {
private Context ctx;
Calendar c = Calendar.getInstance();
int month = c.get(Calendar.MONTH);
int year = c.get(Calendar.YEAR);
ViewGroup collection;
public MyPagerAdapter (Context ctx){
this.ctx = ctx ;
}
#Override
public int getCount() {
return 3;
}
public Object instantiateItem(ViewGroup container, int position ){
this.collection = (ViewPager)container;
NewMonth monthObject = new NewMonth(ctx, month+position-1,2012);
View monthLayout = monthObject.newParentLayout;
collection.addView(monthLayout);
return monthLayout;
return addViewAt(position);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
collection.removeViewAt(position);
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public boolean isViewFromObject(View view, Object arg1) {
return view==arg1;
}
}
You have to maintain all tabs in memory specifying the OffscreenPageLimit to N-1, in your case put this inside the onCreate method:
myPager.setOffscreenPageLimit(2);
Checkout populate() function from ViewPager source - it has clear checks then to remove currentIndex+1 and currentIndex-1 items. Removing is done based on view sizes and it seems to be entirely internal ViewPager logic. ViewPager source is located
<android sdk folder>\extras\android\support\v4\src\java\android\support\v4\view\ViewPager.jav‌​a
.
You might debug ViewPager to know that is happening exactly, but I wouldn't suggest so until You faced some serious issue with ViewPager. What's why: if you dig into ViewPager code it might lead You to write some hackish code (even not intentionally) on it based on its internal structure and not on its public interface and documentation. So, the main idea of data encapsulation would be ruined which is definitely not good (sadly, sometimes we need to do so in Android due to lack of documentation / unclear naming / android internal issues etc., check Code Complete by Steve McConnell for more details on good encapsulation etc.).
Here the key is that position is different then index. If they give you a position there is no guarantee that your collections haven't removed other positions.
Example:
Let's say your at position 2. destroyItem might have been called for position 0 which means in your collections now position 2 is actually at index 1. So your indexes will quickly become out of sync from your positions. The same thing happens with listview children. I would recommend using a sparseArray instead.
private final SparseArray<View> views = new SparseArray<>();
public View instantiateItem(ViewGroup container, final int position) {
...
views.put(position, view);
...
}
public void destroyItem(ViewGroup container, int position, Object object) {
View view = views.get(position);
if (view != null) {
container.removeView(view);
views.remove(position);
}
}

Categories

Resources