Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to implement viewpager and views in single xml file

UPDATED : Can I use the following layout to implement 3 textviews in Viewpager :

<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">

       <TextView
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:text="view 1"/>
       <TextView
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:text="view 2"/>
       <TextView
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:text="view 3"/>

    </android.support.v4.view.ViewPager>
</LinearLayout>

I want to implement the ViewPager for these 3 views. and i want to have viewpager and those 3 views in single xml file. Each page contains each textview. I have seen some examples but each page was implement using separate xml layout file.

How can I implement the viewpager for these 3 views in a single xml file. If possible please provide me a sample code or example.

like image 639
Dileep Perla Avatar asked Sep 06 '12 07:09

Dileep Perla


People also ask

How do you implement a pager view?

Implement Swipe Views You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, you need to add a dependency on ViewPager and on Material Components to your project. To insert child views that represent each page, you need to hook this layout to a PagerAdapter .

Is ViewPager deprecated?

This method may be called by the ViewPager to obtain a title string to describe the specified page. This method is deprecated.


2 Answers

You can use a single XML layout nesting the children views.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

        <LinearLayout
            android:id="@+id/page_one"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
                    <TextView
                    android:text="PAGE ONE IN"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textColor="#fff"
                    android:textSize="24dp"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/page_two"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
                    <TextView
                    android:text="PAGE TWO IN"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textColor="#fff"
                    android:textSize="24dp"/>
        </LinearLayout>

    </android.support.v4.view.ViewPager>

</LinearLayout>

BUT... you need handle this with an adapter also. Here we return the finded view ID without inflate any other layout.

    class WizardPagerAdapter extends PagerAdapter {

        public Object instantiateItem(View collection, int position) {

            int resId = 0;
            switch (position) {
            case 0:
                resId = R.id.page_one;
                break;
            case 1:
                resId = R.id.page_two;
                break;
            }
            return findViewById(resId);
        }

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == ((View) arg1);
        }
    }



    // Set the ViewPager adapter
    WizardPagerAdapter adapter = new WizardPagerAdapter();
    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(adapter);

My question is... Some Guru here can teach me if is possible that the ViewPager read the children from XML and auto build the pages without use the instantiateItem()?

like image 188
jjalonso Avatar answered Sep 18 '22 18:09

jjalonso


Update

This answer will show optimised and managed way to set ViewPager pages inside layout.

Step 1

First make two pages Layouts XML layout_page_1.xml and layout_page_2.xml.

Step 2

Now include all pages layout in your parent layout ViewPager.

<androidx.viewpager.widget.ViewPager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/page_one"
        layout="@layout/layout_page_1" />

    <include
        android:id="@+id/page_two"
        layout="@layout/layout_page_2" />

</androidx.viewpager.widget.ViewPager>

Step 3

Now from your code, set adapter in simple steps

// find views by id
ViewPager viewPager = findViewById(R.id.viewpager);

CommonPagerAdapter adapter = new CommonPagerAdapter();

// insert page ids
adapter.insertViewId(R.id.page_one);
adapter.insertViewId(R.id.page_two);

// attach adapter to viewpager
viewPager.setAdapter(adapter);

That's All! You need only a common adapter for all ViewPagers.

CommonPagerAdapter.java class

public class CommonPagerAdapter extends PagerAdapter {
    private List<Integer> pageIds = new ArrayList<>();

    public void insertViewId(@IdRes int pageId) {
        pageIds.add(pageId);
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        return container.findViewById(pageIds.get(position));
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView((View) object);
    }

    @Override
    public int getCount() {
        return pageIds.size();
    }

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

Important Note

It is better to use Fragments instead of Views. You should create Fragments and use FragmentStatePagerAdapter to maintain stack, lifecycle and states. You can see @this answer for complete code of using FragmentStatePagerAdapter.

like image 24
Khemraj Sharma Avatar answered Sep 18 '22 18:09

Khemraj Sharma