Android ViewPager +Fragment+TabLayout从易到难讲解

       ViewPager 让我印象最深的是,APP的引导页,当我们下载好一个软件点进去,APP就会有三张这样的引导页(告诉用户这款APP基本用途和操作)。当然,ViewPager 不止这样,

       ViewPager 最大作用就是允许使用者滑动数据页面,简单的说ViewPager 是一种布局管理器。它是android扩展包v4包中的类。ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。和List很像,需要通过适配器(PagerAdapter)来提供数据,同时官方还推荐我们ViewPager和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。

     从ViewPager 简单例子开始学习吧!三步骤:

一:主布局加入ViewPager ,另外写三个滑动布局view:

activity_view_pager.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.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

    </android.support.v4.view.ViewPager>

</RelativeLayout>

第二步:完善适配器,
public class ViewPagerAdapter extends PagerAdapter {
    private List<View> viewList;
    public ViewPagerAdapter(List<View> viewList){
        this.viewList=viewList;
    }
    /**
     *返回页卡的数量
     * @return
     */
    @Override
    public int getCount() {
        return viewList.size();
    }

    /**
     *判断view是否来自于对象
     * @param view
     * @param object
     * @return
     */
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==object;
    }

    /**
     *实例化一个页卡
     * @param container
     * @param position
     * @return
     */
    @Override
    public Object instantiateItem(ViewGroup container,
                                  int position) {
        container.addView(viewList.get(position));
        return viewList.get(position);
    }

    /**
     * 销毁一个页卡
     * @param container
     * @param position
     * @param object
     */
    @Override
    public void destroyItem(ViewGroup container, 
                            int position, Object object) {
        container.removeView(viewList.get(position));
    }
}
第三步:java代码部分
package com.example.dell.viewpagertest;

import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.util.ArrayList;
import java.util.List;

public class MyViewPager extends AppCompatActivity {
    private ViewPager viewPager;
    private View view1,view2,view3;
    private List<View> list;
    private ViewPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);
        initLayout();//初始化实例方法
        //创建PagerAdapter适配器
        pagerAdapter=new ViewPagerAdapter(list);
        //ViewPager加载适配器
        viewPager.setAdapter(pagerAdapter);
    }
    public void initLayout(){
        viewPager=(ViewPager) findViewById(R.id.view_pager);
        list=new ArrayList<View>();
        //通过View对象去作为ViewPager数据源
        view1=View.inflate(this,R.layout.layout_view1,null);
        view2=View.inflate(this,R.layout.layout_view2,null);
        view3=View.inflate(this,R.layout.layout_view3,null);
        list.add(view1);
        list.add(view2);
        list.add(view3);
    }
}
效果图:

主布局的话,记得添加的是V4包的ViewPager ,同时别忘了 android :layout_gravity= "center"。
咱们重点关注 适配器(PagerAdapter),继承这个类的时候,我们至少需要重写它的四个方法:
  • int getCount() 
  • boolean isViewFromObject(View arg0, Object arg1)
  • Object instantiateItem(ViewGroup container, int position)
  • void destroyItem(ViewGroup container, int position,Object object)

      ViewPager 可以加入标题,让标题指引滑动,PagerTitleStrip和PagerTabStrip都是ViewPager 当前页面上一个页面和下一个页面的非交互指示器,一般作为ViewPager 子控件被添加到xml布局文件中。通过android:layout_gravity""属性设置为top或bottom来决定它显示在ViewPager 的头部或底部。每个页面的标题是通过适配器的getPageTitle(int)函数提供给ViewPager的。这里只讲一个,因为他们的用法一样,就简单说说他们的不同点吧!

我们通过上面的例子来进行修改,只贴出部分增加的代码:

主布局文件:

<?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.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

        <android.support.v4.view.PagerTitleStrip
            android:id="@+id/pager_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top">

        </android.support.v4.view.PagerTitleStrip>

    </android.support.v4.view.ViewPager>

</RelativeLayout>

适配器我们增加了一个方法和一个构造内容:

private List<View> viewList;
private List<String> tabList;
public ViewPagerAdapter(List<View> viewList,List<String> tabList){
    this.viewList=viewList;
    this.tabList=tabList;
}
 
 
/**
 * 根据位置返回当前所对应的标题。
 * @param position
 * @return
 */
@Override
public CharSequence getPageTitle(int position) {
    return tabList.get(position);
}
 
 
最后是java代码:
 
 
private List<String> tabList;//标题
private PagerTitleStrip titleStrip;

//标题
titleStrip=(PagerTitleStrip) findViewById(R.id.pager_title);
tabList=new ArrayList<String>();
tabList.add("TAB1");
tabList.add("TAB2");
tabList.add("TAB3");

//创建PagerAdapter适配器
pagerAdapter=new ViewPagerAdapter(list,tabList);

 效果图:

       从效果图来看, 些小伙伴可能想到,我们可不可以点击来滑动 呢?还有一个问题,我们上面是直接将布局设置为背景图片,那如果是一百张照片,那不成我们要写一百个布局,这太恐怖了吧!其实ViewPager 和碎片一起使用,效果会更好,官方强力推荐我们那样做。效果图看着不怎么优美,我们来看看终极版例子:ViewPager +Fragment+TabLayout

主布局:还有其他三个布局,不贴了,都是背景图片,自己弄(和上面例子一样)。
<?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:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="40sp">

    </android.support.design.widget.TabLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/tab_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>
</LinearLayout>
加载碎片布局:只贴一个,其他两个类也一样,
public class TabFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_tab1,
                container, false);
    }
}
适配器:
public class MyTabAdapter extends FragmentPagerAdapter{

    private List<Fragment> fragmentList;
    private List<String> stringList;//存放标题
    public MyTabAdapter(FragmentManager fm, 
                        List<Fragment> fragmentList,
                        List<String> stringList){
        super(fm);
        this.stringList=stringList;
        this.fragmentList=fragmentList;
    }
    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

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

    //此方法用来显示tab上的名字
    @Override
    public CharSequence getPageTitle(int position) {

        return stringList.get(position % stringList.size());
    }

}
Java代码:
package com.xhm.dell.zaiwo;

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

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

public class MyZaiWo extends FragmentActivity {

    private TabLayout tabLayout;
    private ViewPager viewPager;
    private List<Fragment> fragmentList;
    private List<String> stringList;//存放标题
    private MyTabAdapter tabAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_zai_wo);
        viewPager=(ViewPager)findViewById(R.id.tab_pager);
        tabLayout=(TabLayout)findViewById(R.id.tab_layout);
        stringList=new ArrayList<String>();
        stringList.add("TAB1");
        stringList.add("TAB2");
        stringList.add("TAB3");

        fragmentList=new ArrayList<Fragment>();
        fragmentList.add(new TabFragment());
        fragmentList.add(new TabFragment2());
        fragmentList.add(new TabFragment3());

        tabAdapter=new MyTabAdapter(getSupportFragmentManager()
                ,fragmentList,stringList);
        viewPager.setAdapter(tabAdapter);

        tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
        /*也可以这样写
        TabLayout.Tab tab1 = tabLayout.newTab().setText("Tab1");
        tabLayout.addTab(tab1);
        TabLayout.Tab tab2 = tabLayout.newTab().setText("Tab2");
        tabLayout.addTab(tab2);
        TabLayout.Tab tab3 = tabLayout.newTab().setText("Tab3");
        tabLayout.addTab(tab3);
         */
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);
    }
}
效果图:
怎么样?是不是美多了。看看代码中又有那些变化了:
布局中多出了个TabLayout,不用担心,这个不难(自己学一下,会了更好)

java代码中,我们继承的是 FragmentActivity而不是Activity了,为咋?这里因为我们要兼容是3.0以下版本,所以需继承FragmentActivity,通过getSupportFragmentManager()获取FragmentManager;3.0及其以上版本,只需继承Activity,通过getFragmentManager获取事务。

重点说下适配器:

谷歌官方认为,ViewPager应该和Fragment一起使用时,此时ViewPager的适配器应该是FragmentPagerAdapter,当你实现一个FragmentPagerAdapter,你必须至少覆盖以下方法:

getCount() //还回view的数量

getItem()

  • 该类中新增的一个虚函数。函数的目的为生成新的 Fragment 对象。重载该函数时需要注意这一点。在需要时,该函数将被 instantiateItem() 所调用。
  • 如果需要向 Fragment 对象传递相对静态的数据时,我们一般通过 Fragment.setArguments() 来进行,这部分代码应当放到 getItem()。它们只会在新生成 Fragment 对象时执行一遍。
  • 如果需要在生成 Fragment 对象后,将数据集里面一些动态的数据传递给该 Fragment,那么,这部分代码不适合放到 getItem() 中。因为当数据集发生变化时,往往对应的 Fragment 已经生成,如果传递数据部分代码放到了 getItem() 中,这部分代码将不会被调用。这也是为什么很多人发现调用 PagerAdapter.notifyDataSetChanged() 后,getItem() 没有被调用的一个原因。
除了这个适配器还有一个适配器(FragmentStatePagerAdapter)。这两个适配器都是 继承自 PagerAdapter,更专注于每一页均为 Fragment 的情况。FragmentPagerAdapter类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter适配器。

Android ViewPager滑滑的~~~



猜你喜欢

转载自blog.csdn.net/l_201607/article/details/70808910