首先我们看一下效果
这就是ViewPager——视图翻页工具,我们平时在App上看到的新闻、淘宝最上面一栏的导航、看视频时的推荐,都是利用ViewPager实现的
ViewPager 直接继承了 ViewGroup,所有它是一个容器类,可以在其中添加其他的 view 类。
ViewPager 需要一个 PagerAdapter 适配器类给它提供数据。
ViewPager 经常和 Fragment 一起使用,并且提供了专门的 FragmentPagerAdapter 和 FragmentStatePagerAdapter 类供 Fragment 中的 ViewPager 使用。
fragment的生命周期会执行
onDestoryView
onDestory
onCreate
onCreateView
fragment会被销毁
适用用 图片预览等多个fragment的情况
onDestoryView
onCreateView
fragment不会被销毁
适用于引导页等少个fragment的情况
像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两个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;
}
}