anndroid使用ViewPager实现三个fragment切换

时间:2021-05-20

一、ViewPager的基本用法

1.ViewPager概述

ViewPager是android扩展包v4包中的类,这个类可以让我们左右切换当前的view。我们先来聊聊ViewPager的几个相关知识点:

  • ViewPager类直接继承了ViewGroup类,因此它一个容器类,可以添加其他的view类
  • ViewPager类需要一个PagerAdapter适配器类给它提供数据(这点跟ListView一样需要数据适配器Adater)
  • ViewPager经常和Fragment一起使用,并且官方还提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用
  • 2.ViewPager使用案例

    我们只需在xml布局文件中添加如下代码:

    activity_main.xml:

    <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=".MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="wrap_content"> </android.support.v4.view.ViewPager></RelativeLayout>

    tab.xml(作为ViewPager的子布局):

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tab1" /></LinearLayout>

    然后这里我们先创建4个要在ViewPager中显示的界面,代码如下:

    ArrayList<View> viewContainter = new ArrayList<View>();View view1 = LayoutInflater.from(this).inflate(R.layout.tab1, null);View view2 = LayoutInflater.from(this).inflate(R.layout.tab2, null);View view3 = LayoutInflater.from(this).inflate(R.layout.tab3, null);View view4 = LayoutInflater.from(this).inflate(R.layout.tab4, null);//viewContainter添加viewviewContainter.add(view1);viewContainter.add(view2);viewContainter.add(view3);viewContainter.add(view4);

    有了数据后我们就要创建数据适配器了,我们创建一个数据适配器MyPagerAdapter继承自PagerAdapter,在PagerAdapter我们必须重写以下几个方法:

    int getCount()
    getCount():返回可以滑动的VIew的个数

    void destroyItem(ViewGroup container, int position,Object object)
    从当前container中删除指定位置的View

    Object instantiateItem(ViewGroup container, int position)
    将当前视图添加到container中并返回当前View视图

    boolean isViewFromObject(View arg0, Object arg1)
    该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Object与一个页面视图是否是代表的同一个视图,官方建议直接返回arg0 == arg1即可。

    下面我们给出MyPagerAdapters完整代码:

    /*** ViewPager的数据适配器*/class MyPagerAdapters extends PagerAdapter{ //返回可以滑动的VIew的个数 @Override public int getCount() { return viewContainter.size(); } //滑动切换的时候销毁当前的组件 @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView(viewContainter.get(position)); } //将当前视图添加到container中并返回当前View视图 @Override public Object instantiateItem(ViewGroup container, int position) { ((ViewPager) container).addView(viewContainter.get(position)); return viewContainter.get(position); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; }

    最后我们只要把MyPagerAdapters适配器设置给ViewPager即可:

    pager = (ViewPager) this.findViewById(R.id.viewpager);pager.setAdapter(new MyPagerAdapters());

    MainActivity完整代码如下:

    package com.zejian.viewpager;import android.annotation.SuppressLint;import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.PagerTabStrip;import android.support.v4.view.ViewPager;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;public class MainActivity extends Activity { ViewPager pager = null; PagerTabStrip tabStrip = null; ArrayList<View> viewContainter = new ArrayList<View>(); @SuppressLint("ResourceAsColor") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pager = (ViewPager) this.findViewById(R.id.viewpager); View view1 = LayoutInflater.from(this).inflate(R.layout.tab1, null); View view2 = LayoutInflater.from(this).inflate(R.layout.tab2, null); View view3 = LayoutInflater.from(this).inflate(R.layout.tab3, null); View view4 = LayoutInflater.from(this).inflate(R.layout.tab4, null); //viewpager开始添加view viewContainter.add(view1); viewContainter.add(view2); viewContainter.add(view3); viewContainter.add(view4); //设置Adapter pager.setAdapter(new MyPagerAdapters()); } /** * ViewPager的数据适配器 */ class MyPagerAdapters extends PagerAdapter{ //返回可以滑动的VIew的个数 @Override public int getCount() { return viewContainter.size(); } //滑动切换的时候销毁当前的组件 @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView(viewContainter.get(position)); } //将当前视图添加到container中并返回当前View视图 @Override public Object instantiateItem(ViewGroup container, int position) { ((ViewPager) container).addView(viewContainter.get(position)); return viewContainter.get(position); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } }}

    到此,最简单的ViewPager使用方式已经介绍完啦。

    3.PagerTitleStrip类和PagerTabStrip类

    我们在编写ViewPager的应用时,还会使用到两个组件类分别是PagerTitleStrip类和PagerTabStrip类,PagerTitleStrip类直接继承自ViewGroup类,用于设置每页的标题,而PagerTabStrip类继承PagerTitleStrip类用于控制Tab选择时指示条样式或者标题样式,这两个类也都是容器类。但是有一点我们需要特别需要注意, 在定义XML的layout的时候,这两个类必须是ViewPager标签的子标签,不然会出错 。由于PagerTabStrip类继承PagerTitleStrip类,因此PagerTabStrip拓展了PagerTitleStrip类功能,所以这里我们仅演示PagerTabStrip用法。

    首先我们在activity_main.xml文件中添加PagerTabStrip控件:

    <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=".MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="wrap_content"> <android.support.v4.view.PagerTabStrip android:id="@+id/tabstrip" android:layout_width="wrap_content" android:layout_height="50dip" android:gravity="center" /> </android.support.v4.view.ViewPager></RelativeLayout>

    接着我们在MainActivity.java文件中创建标题数据:

    ArrayList<String> titleContainer = new ArrayList<String>();//页签项
titleContainer.add("今日头条");
titleContainer.add("今天热点");
titleContainer.add("今日财经");
titleContainer.add("今日军事");

    想要为每个标签页添加标题,我们必须重写PagerAdapter类中的getPageTitle方法,然后根据位置position从集合数据中获取对应的title返回即可,该方法实现如下:

    @Overridepublic CharSequence getPageTitle(int position) { return titleContainer.get(position);}

    接下来我们来通过PagerTabStrip控件改变每个Tab的下横线指示线的style。代码如下:

    tabStrip = (PagerTabStrip) this.findViewById(R.id.tabstrip);//取消tab下面的长横线tabStrip.setDrawFullUnderline(false);//设置tab的背景色tabStrip.setBackgroundResource(R.color.bg);//设置当前tab页签的下划线颜色tabStrip.setTabIndicatorColorResource(R.color.red);tabStrip.setTextSpacing(400);

    到此标题和指示器都设置完成,下面我们给出改版后的MainActivity代码:

    package com.zejian.viewpager;import android.annotation.SuppressLint;import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.PagerTabStrip;import android.support.v4.view.ViewPager;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;public class MainActivity extends Activity { ViewPager pager = null; PagerTabStrip tabStrip = null; ArrayList<View> viewContainter = new ArrayList<View>(); ArrayList<String> titleContainer = new ArrayList<String>(); @SuppressLint("ResourceAsColor") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pager = (ViewPager) this.findViewById(R.id.viewpager); tabStrip = (PagerTabStrip) this.findViewById(R.id.tabstrip); //取消tab下面的长横线 tabStrip.setDrawFullUnderline(false); //设置tab的背景色 tabStrip.setBackgroundResource(R.color.bg); //设置当前tab页签的下划线颜色 tabStrip.setTabIndicatorColorResource(R.color.red); tabStrip.setTextSpacing(400); View view1 = LayoutInflater.from(this).inflate(R.layout.tab1, null); View view2 = LayoutInflater.from(this).inflate(R.layout.tab2, null); View view3 = LayoutInflater.from(this).inflate(R.layout.tab3, null); View view4 = LayoutInflater.from(this).inflate(R.layout.tab4, null); //viewpager开始添加view viewContainter.add(view1); viewContainter.add(view2); viewContainter.add(view3); viewContainter.add(view4); //页签项 titleContainer.add("今日头条"); titleContainer.add("今天热点"); titleContainer.add("今日财经"); titleContainer.add("今日军事"); pager.setAdapter(new MyPagerAdapters()); } /** * ViewPager的数据适配器 */ class MyPagerAdapters extends PagerAdapter{ //返回可以滑动的VIew的个数 @Override public int getCount() { return viewContainter.size(); } //滑动切换的时候销毁当前的组件 @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView(viewContainter.get(position)); } //将当前视图添加到container中并返回当前View视图 @Override public Object instantiateItem(ViewGroup container, int position) { ((ViewPager) container).addView(viewContainter.get(position)); return viewContainter.get(position); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public CharSequence getPageTitle(int position) { return titleContainer.get(position); } }}

    实际上在我们开发中很少会使用到PagerTabStrip与PagerTitleStrip,因为他们实现的标题栏效果很不好,不能指定一个页面一次显示一个,或者全部显示,而且标题还跟着界面滑动。因此实际应用中并不建议使用。我们更多的是去自定义指示器,这样的话效果也会更好,好了,到此,本篇到此告一段落。

    Fragment+ViewPager的基本用法

    1.FragmentPagerAdapter与FragmentStatePagerAdapter

    当ViewPager与Fragment结合使用时,我们所需要使用的数据适配器就已不再是PagerAdapter而是官方另外提供的FragmentPagerAdapter与FragmentStatePagerAdapter数据适配器,下面我们先来聊聊这两个FragmentPagerAdapter与FragmentStatePagerAdapter的使用方法及其主要区别。

    FragmentPagerAdapter

    FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。该类内的每一个生成的 Fragment 都将保存在内存之中,尽管不可见的视图有时会被销毁,但用户所有访问过的fragment都会被保存在内存中,因此fragment实例会保存大量的各种状态,这就造成了很大的内存开销。所以FragmentPagerAdapter比较适用于那些相对静态的页,数量也比较少的应用情景,如主流主界面;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。对应实现FragmentPagerAdapter ,我们只需重写getCount()与getItem()两个方法,因此相对于继承自 PagerAdapter,更方便一些。接下来我们来看看如何用代码实现FragmentPagerAdapter

    class MyFragmentAdapter extends FragmentPagerAdapter{ List<Fragment> list; public MyFragmentAdapter(FragmentManager fm,List<Fragment> list) { super(fm); this.list=list; } /** * 返回需要展示的fragment * @param position * @return */ @Override public Fragment getItem(int position) { return list.get(position); } /** * 返回需要展示的fangment数量 * @return */ @Override public int getCount() { return list.size(); }}

    代码相当简单,我们这里简单以下两个函数

    getItem(int position)
    这个函数实际上是根据下标position需要展示的fragment界面,该方法是在PagerAdapter#instantiateItem()方法中被调用的,大家只要看一下FragmentPagerAdapter源码就清晰了。

    getCount()
    这个函数就更简单了,返回需要展示的fragment的总个数。

    到此我们就对FragmentPagerAdapter介绍完了,下面我们接着看看FragmentStatePagerAdapter类。

    FragmentStatePagerAdapter

    FragmentStatePagerAdapter 和 FragmentPagerAdapter 一样,是继承子 PagerAdapter。但是它们的不同点在于其类名中的 ‘State' 所表明的含义一样,该 PagerAdapter 的实现将只保留当前页面,当页面离开视线后,就会被消除,释放其资源;而在页面需要显示时,再生成新的页面。这样实现的最大好处在于当拥有大量的页面时,不必在内存中占用大量的内存。我们在实现FragmentStatePagerAdapter是也同样只需重写getCount()与getItem()两个方法,而且其方法含义跟FragmentPagerAdapter是一样的。下面我们来看看实现案例,其实就改了个继承类而已。

    class MyFragmentStateAdapter extends FragmentStatePagerAdapter{ List<Fragment> list; public MyFragmentStateAdapter(FragmentManager fm,List<Fragment> list) { super(fm); this.list=list; } /** * 返回需要展示的fragment * @param position * @return */ @Override public Fragment getItem(int position) { return list.get(position); } /** * 返回需要展示的fangment数量 * @return */ @Override public int getCount() { return list.size(); } }

    从代码的角度来看就换了继承类,其他都没有变化。最后我们来实现一个简单例子;

    我们先来编写需要的Fragment布局.fragment.xml如下:

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv" android:textSize="20dp" android:textColor="@color/white" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>

    FragmentView.java代码如下:

    package com.zejian.activity;package com.zejian.viewpager;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by zejian * Time 16/8/7. * Description: */public class FragmentView extends Fragment { private Bundle arg; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); arg=getArguments(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view= inflater.inflate(R.layout.fragment,null); TextView tv= (TextView) view.findViewById(R.id.tv); int page=arg.getInt("pager_num"); if (page==1){ view.setBackgroundResource(R.color.colorAccent); }else if(page==2){ view.setBackgroundResource(R.color.greed); }else if(page==3){ view.setBackgroundResource(R.color.red); }else if(page==4){ view.setBackgroundResource(R.color.colorPrimary); } tv.setText(arg.getString("Title")); return view; } public static FragmentView newInstance(Bundle args) { FragmentView fragment = new FragmentView(); fragment.setArguments(args); return fragment; }}

    Fragment的代码也很清新,我们通过传递过来的参数去判断每个fragment的背景颜色,并设置标题名称,最后返回我们需要展示的view。我们再来看看actvity的布局文件

    activity_vp_fg.xml

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

    VP_FG_Activity.java

    package com.zejian.viewpager;import android.os.Bundle;import android.support.annotation.Nullable;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.app.FragmentStatePagerAdapter;import android.support.v4.view.ViewPager;import java.util.ArrayList;import java.util.List;/** * Created by zejian * Time 16/8/7. * Description: */public class VP_FG_Activity extends FragmentActivity { private ViewPager viewPager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_vp_fg); viewPager= (ViewPager) findViewById(R.id.vp); initData(); } public void initData(){ List<Fragment> list=new ArrayList<>(); Bundle bundle1=new Bundle(); bundle1.putString("Title","第一个Fragment"); bundle1.putInt("pager_num",1); Fragment fg1=FragmentView.newInstance(bundle1); Bundle bundle2=new Bundle(); bundle2.putString("Title","第二个Fragment"); bundle2.putInt("pager_num",2); Fragment fg2=FragmentView.newInstance(bundle2); Bundle bundle3=new Bundle(); bundle3.putString("Title","第三个Fragment"); bundle3.putInt("pager_num",3); Fragment fg3=FragmentView.newInstance(bundle3); Bundle bundle4=new Bundle(); bundle4.putString("Title","第四个Fragment"); bundle4.putInt("pager_num",4); Fragment fg4=FragmentView.newInstance(bundle4); list.add(fg1); list.add(fg2); list.add(fg3); list.add(fg4); viewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(),list)); } class MyFragmentAdapter extends FragmentPagerAdapter{ List<Fragment> list; public MyFragmentAdapter(FragmentManager fm,List<Fragment> list) { super(fm); this.list=list; } /** * 返回需要展示的fragment * @param position * @return */ @Override public Fragment getItem(int position) { return list.get(position); } /** * 返回需要展示的fangment数量 * @return */ @Override public int getCount() { return list.size(); } } class MyFragmentStateAdapter extends FragmentStatePagerAdapter{ List<Fragment> list; public MyFragmentStateAdapter(FragmentManager fm,List<Fragment> list) { super(fm); this.list=list; } /** * 返回需要展示的fragment * @param position * @return */ @Override public Fragment getItem(int position) { return list.get(position); } /** * 返回需要展示的fangment数量 * @return */ @Override public int getCount() { return list.size(); } }}

    在Activity我们通过以下代码去初始化ViewPager所需要的数据

    List<Fragment> list=new ArrayList<>();Bundle bundle1=new Bundle();bundle1.putString("Title","第一个Fragment");bundle1.putInt("pager_num",1);Fragment fg1=FragmentView.newInstance(bundle1);Bundle bundle2=new Bundle();bundle2.putString("Title","第二个Fragment");bundle2.putInt("pager_num",2);Fragment fg2=FragmentView.newInstance(bundle2);Bundle bundle3=new Bundle();bundle3.putString("Title","第三个Fragment");bundle3.putInt("pager_num",3);Fragment fg3=FragmentView.newInstance(bundle3);Bundle bundle4=new Bundle();bundle4.putString("Title","第四个Fragment");bundle4.putInt("pager_num",4);Fragment fg4=FragmentView.newInstance(bundle4);list.add(fg1);list.add(fg2);list.add(fg3);list.add(fg4);viewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(),list));

    最后把数据时适配器MyFragmentAdapter设置给ViewPager,这样就完成数据的填充。这里有点要注意的是,Activity继承自FragmentActivity,只有FragmentActivity才能内嵌fragment页面,普通Activity是不行的。

    我们运行一下程序到此我们对Fragment+ViewPager的使用方式已经有了比较清晰的了解了,本篇也就告一段落,希望对大家的学习有所帮助,也希望大家多多支持。

    声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

    相关文章