Android: как реализовать viewpager и представления в одном XML-файле

ОБНОВЛЕНО: Могу ли я использовать следующий макет для реализации 3 текстовых представлений в 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>

Я хочу реализовать ViewPager для этих трех представлений. и я хочу иметь viewpager и эти 3 представления в одном XML-файле. Каждая страница содержит каждое текстовое представление. Я видел несколько примеров, но каждая страница была реализована с использованием отдельного файла макета xml.

Как я могу реализовать viewpager для этих 3 представлений в одном XML-файле. Если возможно, пожалуйста, предоставьте мне пример кода или пример.


person Dileep Perla    schedule 06.09.2012    source источник
comment
Можете ли вы добавить образец скриншота.   -  person Sekar    schedule 06.09.2012


Ответы (9)


Как я могу реализовать viewpager для этих 3 представлений в одном XML-файле.

Извините, но это невозможно.

person CommonsWare    schedule 06.09.2012
comment
stackoverflow.com/questions/18710561/ - person Ioane Sharvadze; 16.07.2015
comment
вполне возможно. если вы установите viewPager.setOffscreenPageLimit(N); - person Alp Altunel; 18.07.2017

Вы можете использовать один XML-макет, в котором вложены дочерние представления.

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

НО... вам также нужно справиться с этим с помощью адаптера. Здесь мы возвращаем найденный идентификатор представления без расширения какого-либо другого макета.

    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);

Мой вопрос... Какой-нибудь гуру здесь может научить меня, возможно ли, что ViewPager читает дочерние элементы из XML и автоматически создает страницы без использования instanceItem()?

person jjalonso    schedule 24.10.2012
comment
Вам нужно переопределить метод destroyItem : @Override public void destroyItem(View arg0, int arg1, Object arg2) { } - person Kowlown; 28.04.2013
comment
чтобы дочерний элемент был создан автоматически, вы можете добавить конструктор в адаптер, который принимает пейджер в качестве параметра. внутри элемента создания экземпляра теперь вы можете вернуть pager.getChildAt(position); в то время как в getCount() вы можете вернуть pager.getChildCount() - person Fabio Marcolini; 05.03.2014
comment
Работает как шарм. С помощью этого решения RecyclerView в элементе пейджера автоматически сохраняет свое состояние. (Например, положение прокрутки сохраняется.) - person László Kustra; 11.02.2015
comment
Он перерабатывается, поэтому вам нужно установить для viewpager значение по умолчанию для каждого bindView. - person Ioane Sharvadze; 14.07.2015
comment
Добавить @Override public void destroyItem (родитель ViewGroup, позиция int, объект объекта) { View view = (View) object; родитель.removeView(представление); } - person Alberto Anderick Jr; 10.03.2016

Обновлять

Этот ответ покажет оптимизированный и управляемый способ установки страниц ViewPager внутри макета.

Шаг 1

Сначала создайте две страницы с макетами XML layout_page_1.xml и layout_page_2.xml.

Шаг 2

Теперь включите макет всех страниц в родительский макет 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>

Шаг 3

Теперь из вашего кода установите адаптер простыми шагами

// 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);

Это все! Вам нужен только общий адаптер для всех ViewPager.

Класс CommonPagerAdapter.java

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;
    }
}

Важная заметка

Лучше использовать фрагменты вместо представлений. Вы должны создавать фрагменты и использовать FragmentStatePagerAdapter для поддержки стека, жизненного цикла и состояний. Вы можете увидеть @this answer полный код использования FragmentStatePagerAdapter.

person Khemraj Sharma    schedule 16.11.2018
comment
Если вы ищете подходящий пример из Google: github.com/googlesamples/android-media-controller/blob/ - person Shailendra Yadav; 22.09.2020

это невозможно. вы можете сделать это так

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/pager"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

затем создайте отдельный файл xml и сделайте это так. например: я буду использовать имя файла xml ios_frag.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="50sp"/>
 </LinearLayout>
person Community    schedule 28.01.2014

Просто, если кто-то сталкивается с той же проблемой, я решил ее с помощью адаптера, который извлекает просмотры страниц из произвольной группы просмотра, которую вы ему передаете.

    package com.packagename;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

public class ViewGroupPagerAdapter extends PagerAdapter {
    public ViewGroupPagerAdapter(ViewGroup viewGroup) {
        while (viewGroup.getChildCount() > 0) {
            views.add(viewGroup.getChildAt(0));
            viewGroup.removeViewAt(0);
        }
    }

    private List<View> views = new ArrayList<View>();

    @Override
    public Object instantiateItem(ViewGroup parent, int position) {
        View view = views.get(position);
        ViewPager.LayoutParams lp = new ViewPager.LayoutParams();
        lp.width = ViewPager.LayoutParams.FILL_PARENT;
        lp.height = ViewPager.LayoutParams.FILL_PARENT;
        view.setLayoutParams(lp);
        parent.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup parent, int position, Object object) {
        View view = (View) object;
        parent.removeView(view);
    }

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

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

Применение:

ViewPager viewPager=findViewById(...); // Retrieve the view pager
viewPager.setAdapter(new ViewGroupPagerAdapter(findViewById(R.id.id_of_your_view_group_where_you_store_the_pages)));
person Aron Lorincz    schedule 04.06.2014
comment
И как бы вы получили текущее представление в своей основной деятельности? - person Denny; 11.02.2017

Вы можете создать подкласс ViewPager и переопределить onInflate.
Кроме того, вы получите предварительный просмотр первой страницы ViewPager в редакторе макетов.
Все представления хранятся в памяти, поэтому из соображений производительности вы должны использовать это только с небольшим числом страниц.

@Override protected void onFinishInflate() {
    int childCount = getChildCount();
    final List<View> pages = new ArrayList<>(childCount);
    for (int i = 0; i < childCount; i++) {
        View child = getChildAt(i);
        Class<?> clazz = child.getClass();
        if (clazz.getAnnotation(DecorView.class) == null) {
            pages.add(child);
        }
    }
    for (View page : pages) {
        removeView(page);
    }
    setAdapter(new PagerAdapter() {
        @Override public int getCount() {
            return pages.size();
        }

        @Override public Object instantiateItem(ViewGroup container, int position) {
            container.addView(pages.get(position));
            return position;
        }

        @Override public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView(pages.get((Integer)object));
        }

        @Override public boolean isViewFromObject(View view, Object object) {
            return pages.get((Integer)object) == view;
        }
    });
    super.onFinishInflate();
}
person tango24    schedule 06.01.2017

    viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
    viewPager.setAdapter(new MyPagerAdapter(rootView));
    viewPager.setOffscreenPageLimit(3); //or whatever you like

он его кеширует и показывает отлично.

person Alp Altunel    schedule 18.07.2017

добавьте это в свой файл макета xml

<android.support.v4.view.ViewPager 
    android:id="@+id/view_pager"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

создайте 3 Fragment и добавьте каждый TextView для каждого фрагмента. Затем создайте адаптер, который является подклассом PagerAdapter

Хороший пример можно найти здесь

person chip    schedule 06.09.2012
comment
В этом примере фрагменты и пейджер хранятся в отдельных xml-файлах. Я хочу, чтобы оба сохранялись в одном xml файле - person Dileep Perla; 06.09.2012
comment
Что вы пытаетесь достичь? как насчет того, чтобы отредактировать свой вопрос и добавить некоторую информацию, которая может оказаться полезной? - person chip; 06.09.2012

Просто: добавьте ViewPager в свой файл и поместите в свой 3 TextView...

person arnouf    schedule 06.09.2012
comment
Дай мне попробовать. На самом деле я еще не реализовал. Я только что видел примеры того, как это реализовать, и заметил, что код страницы и код Viewpager (xml) реализованы в отдельных файлах. - person Dileep Perla; 06.09.2012