Android:如何在单个 xml 文件中实现 viewpager 和视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12295066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:20:47  来源:igfitidea点击:

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

androidandroid-viewpager

提问by Dileep Perla

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

更新:我可以使用以下布局在 Viewpager 中实现 3 个文本视图:

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

我想为这 3 个视图实现 ViewPager。我想在单个 xml 文件中有 viewpager 和这 3 个视图。每个页面都包含每个文本视图。我看过一些例子,但每个页面都是使用单独的 xml 布局文件实现的。

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.

如何在单个 xml 文件中为这 3 个视图实现 viewpager。如果可能,请为我提供示例代码或示例。

采纳答案by CommonsWare

How can I implement the viewpager for these 3 views in a single xml file.

如何在单个 xml 文件中为这 3 个视图实现 viewpager。

Sorry, but that is not possible.

对不起,但那是不可能的。

回答by jjalonso

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

您可以使用单个 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>

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

但是...您还需要使用适配器处理此问题。在这里,我们返回找到的视图 ID,而不膨胀任何其他布局。

    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()?

我的问题是......这里的一些大师可以教我ViewPager是否可以从XML读取子项并在不使用instantiateItem()的情况下自动构建页面?

回答by Khemraj

Update

更新

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

此答案将显示在布局内设置 ViewPager 页面的优化和托管方式。

Step 1

第1步

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

首先制作两页布局 XMLlayout_page_1.xmllayout_page_2.xml.

Step 2

第2步

Now include all pages layout in your parent layout ViewPager.

现在在您的父布局中包含所有页面布局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

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

就这样!您只需要一个适用于所有 ViewPagers 的通用适配器。

CommonPagerAdapter.java class

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

Important Note

重要的提示

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

最好使用 Fragments 而不是 Views。您应该创建 Fragments 并用于FragmentStatePagerAdapter维护堆栈、生命周期和状态。您可以在@this 上查看完整的 using 代码FragmentStatePagerAdapter

回答by Khemraj

thats impossible .you can do it like these

那是不可能的。你可以这样做

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

then create seperate xml file and do it like this.for eg:i am gonna use the xml file name is ios_frag.xml :

然后创建单独的 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>

回答by Aron Lorincz

Just if anyone faces the same problem, I've solved it with an adapter which extracts the page views from an arbitrary viewgroup that you pass to it.

如果有人遇到同样的问题,我已经使用适配器解决了它,该适配器从您传递给它的任意视图组中提取页面视图。

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

Usage:

用法:

ViewPager viewPager=findViewById(...); // Retrieve the view pager
viewPager.setAdapter(new ViewGroupPagerAdapter(findViewById(R.id.id_of_your_view_group_where_you_store_the_pages)));

回答by tango24

You can subclass ViewPagerand override onInflate.
Moreover, you will get a preview of the first ViewPager page in the Layout Editor.
All views are kept in memory so for performance reasons you should only use this with a small number of pages.

您可以子类化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();
}

回答by Alp Altunel

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

it caches it and shows perfectly.

它缓存它并完美显示。

回答by chip

add this in your xml layout file

将此添加到您的 xml 布局文件中

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

create 3 Fragments and add each TextViewfor every fragment. Then create an adapter that subclassed PagerAdapter

创建 3 Fragments 并TextView为每个片段添加每个。然后创建一个子类化的适配器PagerAdapter

A good example can be found here

一个很好的例子可以在这里找到

回答by arnouf

Simply : add a ViewPager in your file and put inside your 3 TextView...

简单地:在您的文件中添加一个 ViewPager 并放入您的 3 TextView ...