ViewPager within ListView row item
Asked Answered
M

3

7

I have read a lot of related questions regarding this question. However, none of them has been answered. I am trying to add a ViewPager to each row in the ListView where there are two layouts within the pager. I believe this is doable because of SwipeListView.

Now I have implemented it. However, a blank page is showing with a line in the middle. No rows are appearing.

Enter image description here

Here is my code:

MainActivity + ArrayAdapter

public class MainActivity extends Activity {

    ListView list;
    String[] heros;

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

        heros = getResources().getStringArray(R.array.heros);

        list = (ListView) findViewById(R.id.listView1);
        list.setAdapter(new CustomAdapter(this, heros));
    }

    public class CustomAdapter extends ArrayAdapter<String>
    {
        String[] heros;
        Context context;
        public CustomAdapter(Context context, String[] heros) {
            super(context, R.layout.pager_item_list, R.id.listView1, heros);
            // TODO Auto-generated constructor stub
            this.heros = heros;
            this.context = context;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View row = inflater.inflate(R.layout.pager_item_list, parent, false);

            Log.d("how many times", "I really don't know how it should be");

            ViewPager pager = (ViewPager) row.findViewById(R.id.pager);
            pager.setId(position);
            pager.setAdapter(new PagerCustomAdapter());

            pager.setCurrentItem(0);

            return row;
        }
    }
}

Here is my pageAdapter

public class PagerCustomAdapter extends PagerAdapter{
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return 2;
    }

    @Override
    public Object instantiateItem(View container, int position) {
        // TODO Auto-generated method stub

        LayoutInflater inflater = (LayoutInflater) container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        int id = 0;

        Log.d("I am in pagerAdater", "I am here, dammit!");

        switch(position)
        {
            case 0:
                id = R.layout.fragment_top_item;
                break;
            case 1:
                id = R.layout.fragment_bottom_item;
                break;
        }
        View view = inflater.inflate(id, null);
        ((ViewPager)container).addView(view, 0);
        return view;
    }

    @Override
    public void destroyItem(View arg0, int arg1, Object arg2) {
        ((ViewPager) arg0).removeView((View) arg2);
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        // TODO Auto-generated method stub
        return arg0 == ((View) arg1);
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

}

I have tried both pagerAdapter & FragmentPagerAdapter and both had the same result

I added two log messages in getView() and instantiateItem() and both are being read in logcat as expected. There are neither warnings nor errors in LogCat.

What am I missing?

Update

XML of activity_main

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true" >
</ListView>

</RelativeLayout>

XML of pager_item_list

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="vertical" >

    <android.support.v4.view.ViewPager
         android:id="@+id/pager"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>
</LinearLayout>
Monosome answered 25/12, 2013 at 15:5 Comment(7)
First Clean your project and run, tell me the result.Wink
unfortunately the same, I have even tried on my device same resultMonosome
paste your R.layout.activity_main and R.layout.pager_item_list.Wink
please check the updated partMonosome
@Monosome have you solve your problem sir? because i try to implement those code but not workKazim
@Kazim unfortunately i couldn't :(. please update me if you have found an answer. best luckMonosome
Hey, a year later, I found a solution for your problem. I tried to do the same thing and your code helped me, but I had the same issue : nothing displayed on the list. After some changes, I figured out that if you change the "android:layout_height="fill_parent" " in "android:layout_height="60dp" " on the LinearLayout of the pager_item_list.xml, it works well ! Hope it could help !Process
S
1

I am not sure what you're trying to achieve.. Do you want to change the view when a event happens? like when you click on it? or do you want the same result like the SwipeListView.

If you want to change the view you coult try to use a ViewFlipper anc change the layout when the event occurs. But i'm not sure if this is the result you want

Scintillate answered 5/2, 2014 at 20:45 Comment(4)
thanks for your reply it is a good approach, yet not the result I am looking for.Monosome
Can you tell me the exact result you want to achieve? I don't exactly know what you wantScintillate
I want to have ListView that each item has 2 pages first page is the name and icon, then you slide the page of the item and 2 buttons shows, one for delete and one for update. same result as SwipeListView application i have provided earlierMonosome
I don't have a definite answer yes. But i see a few problems. I think the problem has to do with the layout settings. If you want your ListView to be over the whole page, you should set your layout_height of your ListView to match_parent. Then.. the LinearLayout of the pager_item_list the layout_height should be wrap_content... I think this could be the problem because if both the Listview and the item list have no bounds set for their height, they fill up the whole space.. I think that's what you see on your screen. One item that fills up the whole screen. But i'm not sure. Let me knowScintillate
P
1

A ViewPager when used inside a ListView row needs to have a unique android:id (as in each row must have a different id). This is because the FragmentManager that is associated with the ViewPager adapter uses the id along with the position to store the fragments. This means if you just use the defaults things will get overwritten.

Below is a sample PagerAdapter that allows you to override the default makeFragmentName method.

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Parcelable;
import android.support.v13.app.FragmentCompat;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

public abstract class TaggedFragmentPagerAdapter extends PagerAdapter {

    private final FragmentManager mFragmentManager;

    private FragmentTransaction mCurTransaction = null;

    private Fragment mCurrentPrimaryItem = null;

    public TaggedFragmentPagerAdapter(FragmentManager fm) {
        mFragmentManager = fm;
    }

    /**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position);

    public String getItemTag(int position) {
        // Maintain backward compatibility
        return String.valueOf(getItemId(position));
    }

    @Override
    public void startUpdate(ViewGroup container) {
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        // Do we already have this fragment?
        String name = makeFragmentName(position, container.getId(), getItemTag(position));
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            // FIXME : Start fix.
            if (!fragment.isDetached()) {
                mCurTransaction.detach(fragment);
            }
            // FIXME : End fix.
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            mCurTransaction.add(container.getId(), fragment, name);
        }
        if (fragment != mCurrentPrimaryItem) {
            FragmentCompat.setMenuVisibility(fragment, false);
            FragmentCompat.setUserVisibleHint(fragment, false);
        }

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        mCurTransaction.detach((Fragment) object);
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                FragmentCompat.setMenuVisibility(mCurrentPrimaryItem, false);
                FragmentCompat.setUserVisibleHint(mCurrentPrimaryItem, false);
            }
            if (fragment != null) {
                FragmentCompat.setMenuVisibility(fragment, true);
                FragmentCompat.setUserVisibleHint(fragment, true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

    @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return ((Fragment) object).getView() == view;
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
    }

    /**
     * Return a unique identifier for the item at the given position.
     *
     * <p> The default implementation returns the given position. Subclasses should override this method if the positions of items
     * can change. </p>
     *
     * @param position Position within this adapter
     * @return Unique identifier for the item at position
     */
    public long getItemId(int position) {
        return position;
    }

    protected String makeFragmentName(int position, int viewId, String tagName) {
        return "android:switcher:" + viewId + ":" + tagName;
    }
}
Predikant answered 6/10, 2014 at 4:48 Comment(0)
N
0

I faced a similar issue, and what I did is I explicity set the height of the viewPager and its parent. This worked for me.

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="200dip"
    android:orientation="vertical" >

   <android.support.v4.view.ViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="200dip" >
   </android.support.v4.view.ViewPager>
 </LinearLayout>

I don't know if there is a better solution, but if you do get a better solution please comment!

Nananne answered 8/10, 2015 at 5:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.