35. 【Android教程】视频页面:ViewPager

简介: 35. 【Android教程】视频页面:ViewPager

ViewPager 是一种可以让用户通过左右滑动来切换页面的控件,通过它我们可以展示超过屏幕尺寸大小的内容,在某种程度上它可以说是实现多页面的最佳方式,同时 ViewPager 还支持任意动态的添加/删除页面。比如我们可以将不同的类别的内容分别放在不同页面当中,然后通过滑动切换不同的类别从而给用户展示不同的页面,这个在类似百度App等新闻类App中非常适用。在 ViewPager 中插入“娱乐”、“国际”、“体育”、“星座”等等新闻类别,然后在不同的 View 中展示不同的新闻内容,还可以根据用户的喜好动态增加/删除某些页面,接下来就一起来看看如何完成多页视图。



1. ViewPager 的特性

大家在使用 Android 手机的时候一定都见过下图的效果:

没错,这个就是今天的主角——ViewPager 了。在实际开发过程中,我们大多数时候会采用 Fragment 来展示一个页面而不会直接采用 View,在后面的章节学完 Fragment 之后就会知道,Fragment 可以封装 UI 和逻辑,并且会维护自己的生命周期,所以通过 Fragment 我们可以实现更丰富生动的效果,当然对于 ViewPager 的使用而言其实二者几乎没什么差别,我们现在还是把重点放在 ViewPager 上,在后面学完 Fragment 之后只需要做一些简单的改动即可将 View 替换成 Fragment。ViewPager 和前面所学的 ListView/GridView 类似,也需要一个适配器来完成数据的适配,不同的是 ViewPager 有一个专门的适配器——PagerAdapter,所以我们很多的工作也是围绕着 PagerAdapter 展开。

2. PagerAdapter 的使用方法

类似前面所讲的 BaseAdapter 的四个回调接口(不记得的同学可以返回前面章节回顾一下),PagerAdapter 同样也有类似的回调接口,如下:

  • public Object instantiateItem(ViewGroup container, int position):
    根据传入的 position 创建一个 Page,适配器需要在这个回调里网 container 里面添加 View,如下:
public Object instantiateItem(ViewGroup container, int position) {
    View itemView = mLayoutInflater.inflate(R.layout.view_pager, container, false);
 
    TextView textView = itemView.findViewById(R.id.TextView);
    textView.setText("Mybj Android");
    container.addView(itemView);
 
    return itemView;
 }
  • public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object):
    根据传入的 position 移除一个 Page
1. pupublic void destroyItem(ViewGroup container, int position, Object object) {
     container.removeView((View)object);
}
  • gpublic int getCount():
    返回当前 ViewPager 中可用 View 的数量
1. pupublic int getCount() {
    return mList.length;
}

public boolean isViewFromObject(@NonNull View view, @NonNull Object object):

通过instantiateItem()返回的对象可以看做是一个 key,这个方法用来判断传入的 View 是否是之前创建的 key,如下:

public boolean isViewFromObject(View view, Object object) {
    return view == object;
}

常用的一般就是以上四种回调方法,理解起来都比较简单,其中要注意的是getCountisViewFromObject这两个是必须实现的,而instantiateItem()destroyItem()是可选的,不过大多数场景还是推荐大家实现 4 个回调方法。

3. ViewPager 完整示例

本节将通过一个简单的例子学习 ViewPager 的使用,每一个 Page 将会通过一个 View 来实现(在学习了 Fragment 之后,可以尝试将 View 替换成 Fragment)。例子中的每一个 Page 表示一种类别,在切换过程中我们会接收切换的状态回调,同步更新类别标题。



3.1 整体布局

由于每个页面都在 ViewPager 中,所以整体的布局非常简单,我们只需要放置一个 ViewPager 以及一个 TextView 用来显示当前 Page 的标题即可。

<?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:showIn="@layout/activity_main">
 
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
 
    <TextView
        android:text="Num"
        android:textSize="100sp"
        android:id="@+id/text"
        android:layout_marginTop="50dp"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

3.2 Page 页面的布局编写

对于整体布局而言,主要的页面都在 ViewPager 当中,所以我们需要为不同结构的 Page 编写不同的页面,由于本例中每个 Page 的页面结构都一样,所以可以直接复用一套,直接在里面放置一个 ImageView 用于展示类别图片。

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

3.3 适配器的编写

适配这一块主要就是对四个回调接口的实现,其实在第 2 小节的描述中已经展示了各个方法的实现方式。

package com.emercy.myapplication;
 
import android.view.View;
import android.view.ViewGroup;
 
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
 
import java.util.List;
 
public class MyAdapter extends PagerAdapter {
 
    private final List<View> mView;
 
    public MyAdapter(List<View> view) {
        mView = view;
    }
 
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        container.addView(mView.get(position));
        return mView.get(position);
    }
 
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(mView.get(position));
    }
 
    @Override
    public int getCount() {
        return mView.size();
    }
 
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }
}

3.4 MainActivity 主逻辑编写

主逻辑主要的任务就是将前面的布局都用上,并通过 Adapter 将数据和布局串联起来,所以我们需要获取到 ViewPager 中每个 View 的实例,设置类别之后传递给 Adpater,绑定的任务就交由Adpater完成。接下来再监听 ViewPager 的滑动状态从而判断当前切换的位置,从而实现同步更新类别标题,整体代码如下:

 
package com.emercy.myapplication;
 
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
 
import androidx.viewpager.widget.ViewPager;
 
import org.w3c.dom.Text;
 
import java.util.ArrayList;
import java.util.List;
 
 
public class MainActivity extends Activity {
 
    private ViewPager mViewPager;
    private String[] mTitle = new String[]{"苹果", "香蕉", "荔枝"};
    private List<View> mView = new ArrayList<>();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        final TextView tv = findViewById(R.id.text);
        mViewPager = findViewById(R.id.view_pager);
        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 
            }
 
            @Override
            public void onPageSelected(int position) {
                tv.setText(mTitle[position]);
            }
 
            @Override
            public void onPageScrollStateChanged(int state) {
 
            }
        });
 
        ImageView view1 = (ImageView) LayoutInflater.from(this).inflate(R.layout.list_item, null);
        view1.setBackgroundColor(Color.RED);
        view1.setImageResource(R.drawable.apple);
        mView.add(view1);
 
        ImageView view2 = (ImageView) LayoutInflater.from(this).inflate(R.layout.list_item, null);
        view2.setBackgroundColor(Color.GREEN);
        view2.setImageResource(R.drawable.banana);
        mView.add(view2);
 
        ImageView view3 = (ImageView) LayoutInflater.from(this).inflate(R.layout.list_item, null);
        view3.setBackgroundColor(Color.BLUE);
        view3.setImageResource(R.drawable.lychee);
        mView.add(view3);
 
        mViewPager.setAdapter(new MyAdapter(mView));
        tv.setText(mTitle[0]);
    }
}

编译之后效果如下:

通过左右滑动可以切换不同的页面,每个页面对应的一种水果类别,这样就通过 ViewPager 实现了一个简单的页面切换效果。

4. 小节

本节介绍了 ViewPager 的特点及使用场景,并讲解了 ViewPager 的专属适配器——PagerAdapter 的几个回调函数的使用方法,最后采用 ViewPager 实现了一个简单的例子用于切换不同的页面从而展示不同的类别。这一节中是直接采用 View 来承载每一个 Page,而在实际开发中大多数场景会采用 Fragemnt 来承载 Page,不过对于 ViewPager 的使用到同小异,针对 Fragment 系统提供了两种 Adapter:FragmentPageAdapter和FragmentStatePagerAdapter,在学完 Fragement之后大家可以自行修改本节的例子,通过 Fragment 来实现本例的效果。


相关文章
|
10天前
|
网络协议 Android开发 数据安全/隐私保护
Android手机上使用Socks5全局代理-教程+软件
Android手机上使用Socks5全局代理-教程+软件
72 2
|
20天前
|
缓存 网络协议 安全
49. 【Android教程】HTTP 使用详解
49. 【Android教程】HTTP 使用详解
18 1
|
20天前
|
XML 存储 JSON
51. 【Android教程】JSON 数据解析
51. 【Android教程】JSON 数据解析
28 2
|
20天前
|
存储 API 文件存储
47. 【Android教程】SharedPreferences 存储
47. 【Android教程】SharedPreferences 存储
21 2
|
15天前
|
传感器 Android开发 UED
Android统一设置页面竖屏
【6月更文挑战第4天】
|
10天前
|
监控 Android开发 数据安全/隐私保护
安卓kotlin JetPack Compose 实现摄像头监控画面变化并录制视频
在这个示例中,开发者正在使用Kotlin和Jetpack Compose构建一个Android应用程序,该程序 能够通过手机后置主摄像头录制视频、检测画面差异、实时预览并将视频上传至FTP服务器的Android应用
|
17天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的安卓的微博客系统附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的安卓的微博客系统附带文章和源代码部署视频讲解等
26 2
|
20天前
|
存储 安全 大数据
46. 【Android教程】文件存储
46. 【Android教程】文件存储
17 3
|
20天前
|
存储 编解码 Android开发
58. 【Android教程】音频录制:MediaRecord
58. 【Android教程】音频录制:MediaRecord
15 2
|
20天前
|
设计模式 Android开发
44. 【Android教程】广播接收器:Broadcast Receiver
44. 【Android教程】广播接收器:Broadcast Receiver
17 2