介绍ViewPager

首先我们看一下效果
在这里插入图片描述
这就是ViewPager——视图翻页工具,我们平时在App上看到的新闻、淘宝最上面一栏的导航、看视频时的推荐,都是利用ViewPager实现的

ViewPager 直接继承了 ViewGroup,所有它是一个容器类,可以在其中添加其他的 view 类。
ViewPager 需要一个 PagerAdapter 适配器类给它提供数据。
ViewPager 经常和 Fragment 一起使用,并且提供了专门的 FragmentPagerAdapter 和 FragmentStatePagerAdapter 类供 Fragment 中的 ViewPager 使用。

ViewPager适配器介绍

FragmentStatePagerAdapter

fragment的生命周期会执行
onDestoryView
onDestory
onCreate
onCreateView
fragment会被销毁
适用用 图片预览等多个fragment的情况

FragmentPagerAdapter

onDestoryView
onCreateView
fragment不会被销毁
适用于引导页等少个fragment的情况

如何使用ViewPager

像ListView等其它控件,我们还是先需要一个布局文件来显示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp_show"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></androidx.viewpager.widget.ViewPager>
    
</LinearLayout>

然后我们还需要一个显示内容的小布局,就像ListView中的item布局

<?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,可以根据需求添加其它控件-->
    <TextView
        android:text="默认值"
        android:textSize="24sp"
        android:id="@+id/vp_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

ViewPager提供给开发者预先设计好的适配器,所以这里我们之间创建使用即可

public class MyAdapter extends PagerAdapter {

    private Context context;//上下文
    private List<String> list;//数据源

    public MyAdapter(Context context, List<String> list) {
        this.context = context;
        this.list = list;
    }

    //ViewPager总共有几个页面
    @Override
    public int getCount() {
        return list.size();
    }
    //判断一个页面(View)是否与instantiateItem方法返回的Object一致
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    //添加视图
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        //加载vp的布局
        View inflate = View.inflate(context, R.layout.vp_item, null);
        //给布局控件赋值
        TextView textView = inflate.findViewById(R.id.vp_text);
        textView.setText(list.get(position));
        //添加一个布局(不添加无效果)
        container.addView(inflate);
        return inflate;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
//        super.destroyItem(container, position, object);
        //移除视图
        container.removeView((View) object);
    }
}

最后我们要在Activity中创建适配器,准备数据源以及添加视图即可

public class MainActivity extends AppCompatActivity {
    private ViewPager vpShow;
    private List<String> list = new ArrayList<>();
    private MyAdapter myAdapter;
    private Timer timer = new Timer();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        vpShow = (ViewPager) findViewById(R.id.vp_show);
        //初始化数据源
        for (int i = 0; i < 5; i++) {
            list.add("第" + (i + 1) + "项");
        }

        myAdapter = new MyAdapter(this, list);
        vpShow.setAdapter(myAdapter);

        //设置自动翻页
        timer.schedule(new TimerTask() {
            int index = 0;
            @Override
            public void run() {
            //在主线程中跟新ui的方法,不写可能报错
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        vpShow.setCurrentItem(index++);
                    }
                });
                if (index == list.size()) {
                    index = 0;
                }
            }
        }, 0, 2000);


        vpShow.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            //设置翻页到指定位置时取消自动翻页
            @Override
            public void onPageSelected(int position) {
                if (position == list.size()-1){
                    timer.cancel();
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

    }
}

翻页监听

addOnPageChangeListener()

里面有要重写的方法

1 ,onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
页面滑动状态停止前一直调用
position:当前点击滑动页面的位置
positionOffset:当前页面偏移的百分比
positionOffsetPixels:当前页面偏移的像素位置
2, onPageSelected(int position)
滑动后显示的页面和滑动前不同,调用
position:选中显示页面的位置
3 ,onPageScrollStateChanged(int state)
页面状态改变时调用
state:当前页面的状态
SCROLL_STATE_IDLE:空闲状态
SCROLL_STATE_DRAGGING:滑动状态
SCROLL_STATE_SETTLING:滑动后滑翔的状态

ViewPager与Fragment的结合使用

ViewPager两个Adapter方法的区别
在destroyItem()方法中,FragmentStatePagerAdapter调用的是remove()方法,适用于页面较多的情况;FragmentPagerAdapter调用的是detach()方法,适用于页面较少的情况。但是有页面数据需要刷新的情况,不管是页面少还是多,还是要用FragmentStatePagerAdapter,否则页面会因为没有重建得不到刷新

我们先创建好Fragment和Activity的布局文件
Fragment:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".Viewpager_Fragment">


    <TextView
        android:id="@+id/tv_show"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

Activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></androidx.viewpager.widget.ViewPager>

</LinearLayout>

设置适配器及Activity的相关代码

public class Main2Activity extends AppCompatActivity {
    private ViewPager vp;
    private List<Viewpager_Fragment> list = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        vp = (ViewPager) findViewById(R.id.vp);

        for (int i = 0; i < 5; i++) {
            Viewpager_Fragment viewpager_fragment = new Viewpager_Fragment();
            Bundle bundle = new Bundle();
            bundle.putString("name","第"+(i+1)+"页");
            viewpager_fragment.setArguments(bundle);
            list.add(viewpager_fragment);
        }

        vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return list.get(position);
            }

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

    }

最后在Fragment中添加数据并显示

public class Viewpager_Fragment extends Fragment {
    private TextView tvShow;

    public Viewpager_Fragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_viewpager_, container, false);
        tvShow = (TextView) view.findViewById(R.id.tv_show);

        Bundle arguments = getArguments();
        String name = arguments.getString("name");
        tvShow.setText(name);

        return view;
    }

}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐