如何使用不同的片段/布局实现ViewPager

当我启动一个实现ViewPager的活动时,ViewPager创建了各种片段。我想为每个片段使用不同的布局,但问题是ViewPager最多只显示两个布局(1之后所有剩余片段的第二个布局)。

下面是实现ViewPager的刷卡活动的代码:

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

这是碎片的代码

public class MyFragment extends Fragment
{
@Override
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup,    Bundle paramBundle)
{
return paramLayoutInflater.inflate(R.layout.processorlayout, paramViewGroup, false);
}
}

我使用了5个这样的片段,它们都有不同的布局,但ViewPager最多只显示2个。

编辑: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);
}
}
288995 次浏览

由于这是一个经常被问到的问题,我想花时间和精力来详细解释具有多个片段和布局的ViewPager.干得好。

具有多个片段和布局文件的ViewPager-如何

下面是如何实现ViewPager的完整示例 使用不同的片段类型和不同的布局文件。

在本例中,我有3个片段类,每个类有一个不同的布局文件。为了简单起见,片段布局仅在背景颜色上有所不同。当然,任何布局文件都可以用于片段。

FirstFragment.Java具有桔子背景布局,SecondFragment.Java具有绿色的背景布局,而ThirdFragage.Java具有红的背景布局。此外,每个片段显示不同的文本,这取决于它来自哪个类以及它是哪个实例。

还要注意,我使用的是支持库的片段: android.support.v4.app.fragment

MainActivity.Java(初始化ViewPager,并将其适配器作为内部类)。再次查看进口。我使用的是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;
}
}
}

活动_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"
/>

片段类FirstFragment.Java 导入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;
}
}

第一个_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

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

第二个_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_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

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

第三个_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_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>

最终结果如下:

ViewPager包含5个片段,片段1的类型为FirstFragment,并显示第一个_Frag.XML布局,片段2的类型为SecondFragment,并显示第二个_Frag.XML,片段3-5的类型为ThirdFragment并全部显示第三个_Frag.XML.

enter image description here

上面你可以看到5个片段,可以通过向左或向右滑动来切换。当然,同一时间只能显示一个片段。

最后但同样重要的是:

我建议您在每个中使用构造函数为空 片段类.

使用newInstance(...)方法和Bundle来移交参数,而不是通过构造函数移交潜在的参数。

这样,如果分离并重新附加,则可以通过参数存储对象状态。非常类似于附加到IntentsBundles

这也很好:

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

用于添加片段的代码

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

为每个片段创建一个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;


}
}

稍后您可以进行必要的更正..对我来说很有效。

创建视图数组并将其应用于: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);
}


}

在片段中创建新实例,并在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;
}

基本ViewPager示例

此答案是文件本教程公认的答案的简化。其目的是使ViewPager尽快启动并运行。在此之后可以进行进一步的编辑。

enter image description here

XML

为主活动和每个页面(片段)添加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>

片段_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>

电码

这是主要活动的代码。它包括作为内部类的PagerAdapterFragmentOne。如果它们变得太大,或者您在其他地方重用它们,那么您可以将它们移动到它们自己单独的类中。

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

完成了

如果您将上面的三个文件复制并粘贴到您的项目中,您应该能够运行应用程序并在上面的动画中看到结果。

正在进行

你可以用ViewPager做很多事情。请参阅以下链接以开始使用:

2021使用Kotlin、ViewPager2和RecyclerView.Adapter..回答

RecyclerView.Adapter不使用getItem(),但具有getItemViewType()方法。您可以重写此方法以通知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)
}
}

然后,您可以在onBindViewHolder()方法中以不同的方式处理每个布局。