[英]How to implement a ViewPager with different Fragments / Layouts
When I start an activity which implements viewpager, the viewpager created various fragments.当我启动一个实现 viewpager 的活动时,viewpager 创建了各种片段。 I want to use different layouts for each fragment, but the problem is that viewpager shows only two layouts at the max (second layout on all of the remaining fragments after 1).我想为每个片段使用不同的布局,但问题是 viewpager 最多只显示两个布局(1 之后所有剩余片段的第二个布局)。
Here is the code for SwipeActivity which implements the viewpager:这是实现 viewpager 的SwipeActivity的代码:
public class SwipeActivity extends FragmentActivity
{
MyPageAdapter pageAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
pageAdapter = new MyPageAdapter(getSupportFragmentManager());
ViewPager pager=(ViewPager)findViewById(R.id.pager);
pager.setAdapter(pageAdapter);
ActionBar bar = getActionBar();
bar.setDisplayHomeAsUpEnabled(true);
}
/**
* Custom Page adapter
*/
private class MyPageAdapter extends FragmentPagerAdapter
{
public MyPageAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public int getCount()
{
return 5;
}
@Override
public Fragment getItem(int position)
{
switch(position)
{
case 0: return new MyFragment();
case 1: return SecondFragment.newInstance("asdasd");
default : return RamFragment.newInstance("s");
}
}
}
}
Here is the code for the fragments这是片段的代码
public class MyFragment extends Fragment
{
@Override
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)
{
return paramLayoutInflater.inflate(R.layout.processorlayout, paramViewGroup, false);
}
}
I used 5 fragments like this, all having different layouts, but the viewpager shows only 2 at the max.我使用了 5 个这样的片段,它们都有不同的布局,但 viewpager 最多只显示 2 个。
EDIT : code for SecondFragment编辑:SecondFragment 的代码
public class SecondFragment extends Fragment
{
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final SecondFragment newInstance(String paramString)
{
SecondFragment f = new SecondFragment();
Bundle localBundle = new Bundle(1);
localBundle.putString("EXTRA_MESSAGE", paramString);
f.setArguments(localBundle);
return f;
}
@Override
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)
{
return paramLayoutInflater.inflate(R.layout.motherboardlayout, paramViewGroup, false);
}
}
As this is a very frequently asked question, I wanted to take the time and effort to explain the ViewPager with multiple Fragments and Layouts in detail.由于这是一个非常常见的问题,我想花时间和精力详细解释具有多个片段和布局的 ViewPager。 Here you go.干得好。
The following is a complete example of how to implement a ViewPager with different fragment Types and different layout files.下面是一个完整的例子,说明如何使用不同的fragment Types和不同的布局文件来实现一个ViewPager。
In this case, I have 3 Fragment classes, and a different layout file for each class.在这种情况下,我有 3 个 Fragment 类,每个类都有一个不同的布局文件。 In order to keep things simple, the fragment-layouts only differ in their background color .为了简单起见,片段布局仅在背景颜色上有所不同。 Of course, any layout-file can be used for the Fragments.当然,任何布局文件都可以用于片段。
FirstFragment.java has a orange background layout, SecondFragment.java has a green background layout and ThirdFragment.java has a red background layout. FirstFragment.java 的背景布局为橙色,SecondFragment.java 的背景布局为绿色,而 ThirdFragment.java 的背景布局为红色。 Furthermore, each Fragment displays a different text, depending on which class it is from and which instance it is.此外,每个 Fragment 显示不同的文本,具体取决于它来自哪个类以及它是哪个实例。
Also be aware that I am using the support-library's Fragment: android.support.v4.app.Fragment另请注意,我正在使用支持库的片段: android.support.v4.app.Fragment
MainActivity.java (Initializes the Viewpager and has the adapter for it as an inner class). MainActivity.java (初始化 Viewpager 并将其适配器作为内部类)。 Again have a look at the imports .再看看进口。 I am using the android.support.v4
package.我正在使用android.support.v4
包。
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
case 1: return SecondFragment.newInstance("SecondFragment, Instance 1");
case 2: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
case 3: return ThirdFragment.newInstance("ThirdFragment, Instance 2");
case 4: return ThirdFragment.newInstance("ThirdFragment, Instance 3");
default: return ThirdFragment.newInstance("ThirdFragment, Default");
}
}
@Override
public int getCount() {
return 5;
}
}
}
activity_main.xml (The MainActivitys .xml file) - a simple layout file, only containing the ViewPager that fills the whole screen. activity_main.xml (MainActivitys .xml 文件)——一个简单的布局文件,只包含填充整个屏幕的 ViewPager。
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
The Fragment classes, FirstFragment.java import android.support.v4.app.Fragment; Fragment 类, FirstFragment.java import android.support.v4.app.Fragment;
public class FirstFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.first_frag, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
tv.setText(getArguments().getString("msg"));
return v;
}
public static FirstFragment newInstance(String text) {
FirstFragment f = new FirstFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
first_frag.xml first_frag.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_dark" >
<TextView
android:id="@+id/tvFragFirst"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="26dp"
android:text="TextView" />
</RelativeLayout>
SecondFragment.java第二个片段.java
public class SecondFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.second_frag, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragSecond);
tv.setText(getArguments().getString("msg"));
return v;
}
public static SecondFragment newInstance(String text) {
SecondFragment f = new SecondFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
second_frag.xml第二个片段.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_dark" >
<TextView
android:id="@+id/tvFragSecond"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="26dp"
android:text="TextView" />
</RelativeLayout>
ThirdFragment.java第三个片段.java
public class ThirdFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.third_frag, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragThird);
tv.setText(getArguments().getString("msg"));
return v;
}
public static ThirdFragment newInstance(String text) {
ThirdFragment f = new ThirdFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
third_frag.xml第三个片段.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_red_light" >
<TextView
android:id="@+id/tvFragThird"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="26dp"
android:text="TextView" />
</RelativeLayout>
The end result is the following:最终结果如下:
The Viewpager holds 5 Fragments, Fragments 1 is of type FirstFragment, and displays the first_frag.xml layout, Fragment 2 is of type SecondFragment and displays the second_frag.xml, and Fragment 3-5 are of type ThirdFragment and all display the third_frag.xml. Viewpager有5个Fragment,Fragment 1是FirstFragment类型,显示first_frag.xml布局,Fragment 2是SecondFragment类型,显示second_frag.xml,Fragment 3-5是ThirdFragment类型,都显示third_frag.xml .
Above you can see the 5 Fragments between which can be switched via swipe to the left or right.在上面你可以看到 5 个 Fragment,它们之间可以通过向左或向右滑动来切换。 Only one Fragment can be displayed at the same time of course.当然只能同时显示一个 Fragment。
Last but not least:最后但并非最不重要的:
I would recommend that you use an empty constructor in each of your Fragment classes.我建议您在每个 Fragment 类中使用一个空的构造函数。
Instead of handing over potential parameters via constructor, use the newInstance(...)
method and the Bundle
for handing over parameters.不是通过构造函数传递潜在参数,而是使用newInstance(...)
方法和Bundle
来传递参数。
This way if detached and re-attached the object state can be stored through the arguments.这样,如果分离并重新附加,则可以通过参数存储对象状态。 Much like Bundles
attached to Intents
.很像附加到Intents
Bundles
。
Create an array of Views and apply it to: container.addView(viewarr[position]);
创建一个视图数组并将其应用于: container.addView(viewarr[position]);
public class Layoutes extends PagerAdapter {
private Context context;
private LayoutInflater layoutInflater;
Layoutes(Context context){
this.context=context;
}
int layoutes[]={R.layout.one,R.layout.two,R.layout.three};
@Override
public int getCount() {
return layoutes.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view==(LinearLayout)object);
}
@Override
public Object instantiateItem(ViewGroup container, int position){
layoutInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View one=layoutInflater.inflate(R.layout.one,container,false);
View two=layoutInflater.inflate(R.layout.two,container,false);
View three=layoutInflater.inflate(R.layout.three,container,false);
View viewarr[]={one,two,three};
container.addView(viewarr[position]);
return viewarr[position];
}
@Override
public void destroyItem(ViewGroup container, int position, Object object){
container.removeView((LinearLayout) object);
}
}
Code for adding fragment添加片段的代码
public Fragment getItem(int position) {
switch (position){
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
case 3:
return new Fragment4();
default:
break;
}
return null;
}
Create an xml file for each fragment say for Fragment1, use fragment_one.xml as layout file, use the below code in Fragment1 java file.为每个片段创建一个 xml 文件,例如 Fragment1,使用 fragment_one.xml 作为布局文件,在 Fragment1 java 文件中使用以下代码。
public class Fragment1 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one, container, false);
return view;
}
}
Later you can make necessary corrections.. It worked for me.稍后您可以进行必要的更正..它对我有用。
This answer is a simplification of the documentation , this tutorial , and the accepted answer .此答案是对文档、 本教程和已接受答案的简化。 It's purpose is to get a working ViewPager
up and running as quickly as possible.它的目的是让工作的ViewPager
启动并运行。 Further edits can be made after that.之后可以进行进一步的编辑。
Add the xml layouts for the main activity and for each page (fragment).为主活动和每个页面(片段)添加 xml 布局。 In our case we are only using one fragment layout, but if you have different layouts on the different pages then just make one for each of them.在我们的例子中,我们只使用一种片段布局,但是如果您在不同的页面上有不同的布局,那么只需为每个页面制作一个。
activity_main.xml活动_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.verticalviewpager.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
fragment_one.xml fragment_one.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textview"
android:textSize="30sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
This is the code for the main activity.这是主要活动的代码。 It includes the PagerAdapter
and FragmentOne
as inner classes.它包括PagerAdapter
和FragmentOne
作为内部类。 If these get too large or you are reusing them in other places, then you can move them to their own separate classes.如果它们变得太大或者您在其他地方重用它们,那么您可以将它们移动到它们自己的单独类中。
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
public class MainActivity extends AppCompatActivity {
static final int NUMBER_OF_PAGES = 2;
MyAdapter mAdapter;
ViewPager mPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return NUMBER_OF_PAGES;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return FragmentOne.newInstance(0, Color.WHITE);
case 1:
// return a different Fragment class here
// if you want want a completely different layout
return FragmentOne.newInstance(1, Color.CYAN);
default:
return null;
}
}
}
public static class FragmentOne extends Fragment {
private static final String MY_NUM_KEY = "num";
private static final String MY_COLOR_KEY = "color";
private int mNum;
private int mColor;
// You can modify the parameters to pass in whatever you want
static FragmentOne newInstance(int num, int color) {
FragmentOne f = new FragmentOne();
Bundle args = new Bundle();
args.putInt(MY_NUM_KEY, num);
args.putInt(MY_COLOR_KEY, color);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt(MY_NUM_KEY) : 0;
mColor = getArguments() != null ? getArguments().getInt(MY_COLOR_KEY) : Color.BLACK;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one, container, false);
v.setBackgroundColor(mColor);
TextView textView = v.findViewById(R.id.textview);
textView.setText("Page " + mNum);
return v;
}
}
}
If you copied and pasted the three files above to your project, you should be able to run the app and see the result in the animation above.如果您将上面的三个文件复制并粘贴到您的项目中,您应该能够运行该应用程序并在上面的动画中看到结果。
There are quite a few things you can do with ViewPagers.您可以使用 ViewPagers 做很多事情。 See the following links to get started:请参阅以下链接以开始使用:
This is also fine:这也很好:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
}
}
public class FragmentTab1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);
return rootView;
}
}
class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
switch(position){
case 0:
FragmentTab1 fm = new FragmentTab1();
return fm;
case 1: return new FragmentTab2();
case 2: return new FragmentTab3();
}
return null;
}
@Override
public int getCount() {
return 3;
}
}
<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" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/Fragment1" />
</RelativeLayout>
Create new instances in your fragments and do like so in your Activity在您的片段中创建新实例并在您的 Activity 中执行此操作
private class SlidePagerAdapter extends FragmentStatePagerAdapter {
public SlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch(position){
case 0:
return Fragment1.newInstance();
case 1:
return Fragment2.newInstance();
case 2:
return Fragment3.newInstance();
case 3:
return Fragment4.newInstance();
default: break;
}
return null;
}
2021 answer using Kotlin, ViewPager2, and RecyclerView.Adapter... 2021 年答案使用 Kotlin、ViewPager2 和 RecyclerView.Adapter...
RecyclerView.Adapter doesn't use getItem(), but has a method getItemViewType(). RecyclerView.Adapter 不使用 getItem(),但有一个方法 getItemViewType()。 You can override this method to inform onCreateViewHolder() which layout to use.您可以覆盖此方法以通知 onCreateViewHolder() 使用哪个布局。
class SettingsAdapter(val activity: AppCompatActivity): RecyclerView.Adapter<SettingsAdapter.SettingsViewHolder>()
{
// Page names
private val pageName = arrayOf("General", "Privacy Policy", "Terms of Use", "Feedback")
private val pageResource = arrayOf(R.layout.fragment_general, R.layout.fragment_privacy, R.layout.fragment_terms, R.layout.fragment_feedback)
private val pageCount = pageName.size
override fun getItemCount(): Int {
return pageCount
}
override fun getItemViewType(position: Int): Int {
return position
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingsAdapter.SettingsViewHolder
{
val context = parent.context
val inflater = LayoutInflater.from(context)
val settingsView = inflater.inflate(pageResource[viewType], parent, false)
return SettingsViewHolder(settingsView)
}
}
Then you can handle each layout differently in the onBindViewHolder() method.然后您可以在 onBindViewHolder() 方法中以不同方式处理每个布局。
Kotlin code using FragmentStateAdapter Kotlin 代码使用 FragmentStateAdapter
class Adapter(activity: YourActivity):FragmentStateAdapter(activity) {
override fun getItemCount(): Int {
return 2 // number of Fragments to be displayed here: (0,1)
}
override fun createFragment(position: Int): Fragment = when (position) {
0 -> Frag1.newInstance()
1 -> Frag2.newInstance()
else -> throw IllegalStateException("Invalid adapter position")
}
}
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
Only writing this for someone who comes by and needs latest code in Kotlin.只为路过并需要 Kotlin 最新代码的人写这篇文章。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.