View pager实现自动轮播图

2024-01-04 06:20
文章标签 实现 自动 view 轮播 pager

本文主要是介绍View pager实现自动轮播图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

轮播图

首先放上一张常见的轮播图样图:
这是一张神级图片
** 如图这就是常见的轮播图,对于这样的轮播图该怎么实现?
** 下面开始进入正题:
** 看图,通常这样的页面会滚动播放,同时页面的切换也是平滑的,那么我们首先想到的是应该用View Pager,是的,你没有看错,就是ViewPager。
** 首先先贴上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" ><RelativeLayout
        android:layout_width="match_parent"android:layout_height="160dp" ><android.support.v4.view.ViewPager
            android:id="@+id/viewpager"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayout
            android:layout_width="match_parent"android:layout_height="40dp"android:padding="5dp"android:orientation="vertical"android:layout_alignParentBottom="true"android:gravity="center_horizontal"android:background="#66000000" ><TextView
                android:id="@+id/tv_desc"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@android:color/white"android:singleLine="true"android:text="天王盖地虎, 天王盖地虎, 天王盖地虎, " /><LinearLayout android:id="@+id/ll_point_container"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:orientation="horizontal"></LinearLayout></LinearLayout></RelativeLayout></RelativeLayout>

** 我们将这个布局看成是相对布局,在相对布局中,我们将View Pager充满父布局,同时通常我们的轮播图底部会有一栏文字描述和相对应的小圆点指示器。所以我们采用相对布局,这样才能保证在轮播图底部出现文字和圆点,而文字和圆点,通常都是一个方向的排列,那么我们可以将他们放在竖直的线性布局,这样文字放在小圆点的上方,而小圆点通常为一排,所以我们采用水平的线性布局。
** 接下来就是如何通过java代码去实现这些想法了。
** 首先初始化控件:

private void initViews() {viewPager = (ViewPager) findViewById(R.id.viewpager);viewPager.setOnPageChangeListener(this);// 设置页面更新监听
//      viewPager.setOffscreenPageLimit(1);// 左右各保留几个对象ll_point_container = (LinearLayout) findViewById(R.id.ll_point_container);tv_desc = (TextView) findViewById(R.id.tv_desc);}

** 同时对页面的改变设置监听,在页面切换时可以同步的更换文字描述和对应的小圆点。
初始化控件之后,我们就要将这些控件进行相应对的填充和设置,见下文:

    private void initData() {// 初始化要显示的数据// 图片资源id数组imageResIds = new int[]{R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e};// 文本描述contentDescs = new String[]{"是故圣人一守司其门户,审察其所先后,度权量能,校其伎巧短长。","粤若稽古,圣人之在天地间也,为众生之先。","即欲捭之贵周,即欲阖之贵密。周密之贵微,而与道相追。","捭阖者,道之大化,说之变也;必豫审其变化,吉凶大命系焉。","捭阖之道,以阴阳试之,故与阳言者依崇高,与阴言者依卑小。"};// 初始化要展示的5个ImageViewimageViewList = new ArrayList<ImageView>();ImageView imageView;View pointView;LayoutParams layoutParams;for (int i = 0; i < imageResIds.length; i++) {// 初始化要显示的图片对象imageView = new ImageView(this);imageView.setBackgroundResource(imageResIds[i]);imageViewList.add(imageView);// 加小白点, 指示器pointView = new View(this);pointView.setBackgroundResource(R.drawable.selector_bg_point);layoutParams = new LinearLayout.LayoutParams(5, 5);if(i != 0)layoutParams.leftMargin = 10;// 设置默认所有都不可用pointView.setEnabled(false);ll_point_container.addView(pointView, layoutParams);}}

** 由于是轮播图,所以我们不能如同引导页一样,每一个图都设置一个布局页面,所以我们先将图片的资源ID添加到数组中,同时也将对应的文字添加进文字数组中,然后在初始化要展示的5个轮播图,首先我们通过for循环将初始化要显示的图片,通过资源id设置其背景,(也可以通过setSrc来赋值),将image View添加进集合中,应为我们要通过Adapter才能实现页面的加载和显示,同时将小圆点也加载进圆点的线性布局中。

private void initAdapter() {ll_point_container.getChildAt(0).setEnabled(true);tv_desc.setText(contentDescs[0]);previousSelectedPosition = 0;// 设置适配器viewPager.setAdapter(new MyAdapter());// 默认设置到中间的某个位置int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % imageViewList.size());// 2147483647 / 2 = 1073741823 - (1073741823 % 5)viewPager.setCurrentItem(5000000); // 设置到某个位置}

** 然后我们初始化适配器,要想让View Pager实现轮播,同时也可左右滑动,而不会出现滑到头划不动的情况,我们就可以先将View Pager的position设置为一个比较大的数。这样在前后滑动的时候,通常都不会滑动到头。同时配置适配器。

class MyAdapter extends PagerAdapter{@Overridepublic int getCount() {return Integer.MAX_VALUE;}// 3. 指定复用的判断逻辑, 固定写法@Overridepublic boolean isViewFromObject(View view, Object object) {
//          System.out.println("isViewFromObject: "+(view == object));// 当划到新的条目, 又返回来, view是否可以被复用.// 返回判断规则return view == object;}// 1. 返回要显示的条目内容, 创建条目@Overridepublic Object instantiateItem(ViewGroup container, int position) {System.out.println("instantiateItem初始化: " + position);// container: 容器: ViewPager// position: 当前要显示条目的位置 0 -> 4//          newPosition = position % 5int newPosition = position % imageViewList.size();ImageView imageView = imageViewList.get(newPosition);// a. 把View对象添加到container中container.addView(imageView);// b. 把View对象返回给框架, 适配器return imageView; // 必须重写, 否则报异常}// 2. 销毁条目@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {// object 要销毁的对象System.out.println("destroyItem销毁: " + position);container.removeView((View)object);}}

创建适配器,实现4个必须实现的方法,第一个getCount()返回的时view Pager的大小,也就是轮播图片的数量。但是看上图我们返回的是Int的类型的最大值,这样就是i为了避免在图片轮播的时候出现滑到头,无法滑动的情况。
** 第二个方法,isViewFromObject(),就是在view pager滑动时,滑动到新的条目时,对比缓存中的数据,是否缓存中存在,如果缓存中存在,那么就从缓存中取出,如果没有,则加载该视图。

** 第三个方法:instantiaeItem(),返回要显示的条目内容,创建条目,见上图,我们先将position%图片集合的大小,是因为我们在第一个方法中将view Pager的大小设置的很大,所以这里如果直接使用获取到的position就会很大,而如果要通过图片集合image View List取得对应的图片,由于集合的大小为5,那么就会出现空指针的情况,所以我们将position先转换为0-5以内,再取出对应的imageView,同时将image View添加进container容器中,container容器的作用就是将该imageView保存到缓存中,同时将该image View返回出去,创建条目。

** 第四个方法:destroy Item(),将缓存中的不需要的imageView删除。注意:这里是重点——–看我划重点了:第三个方法和第四个方法中的position不是同一个值啊,第三个方法中position是当前view Pager显示的image View对应的position,而第四个方法的position则不是,那到底是多少呢? 看下图↓
view Pager缓存分析
** 红的的是当前的显示图片,而通常view Pager中,会缓存当前布局的前后各一个布局,这样才能保证再图片滑动的时候可以无缝链接,这就是view Pager的默认初始化范围,如果先要增加默认初始化范围可以使用这个方法→:Viewpager.setOffscreenPageLimit(2),其中的参数2,就是将初始化范围增加为当前显示布局的前后各2个布局。所以这个destroy Item中的position就是当前需要移除的布局,如上图,如果第3个布局往左滑动,第四个布局显示为当前布局,那么这里的position就为2,因为2超出了缓存范围,所以要去掉,如果布局3往右滑动,则这里的position就变为4.所以说这个方法的position的值与第三个方法的position的值不对应。
**接下来就是文本和小圆点的加载了:

@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {// 滚动时调用}@Overridepublic void onPageSelected(int position) {// 新的条目被选中时调用System.out.println("onPageSelected: " + position);int newPosition = position % imageViewList.size();//设置文本tv_desc.setText(contentDescs[newPosition]);//      for (int i = 0; i < ll_point_container.getChildCount(); i++) {
//          View childAt = ll_point_container.getChildAt(position);
//          childAt.setEnabled(position == i);
//      }// 把之前的禁用, 把最新的启用, 更新指示器ll_point_container.getChildAt(previousSelectedPosition).setEnabled(false);ll_point_container.getChildAt(newPosition).setEnabled(true);// 记录之前的位置previousSelectedPosition  = newPosition;}@Overridepublic void onPageScrollStateChanged(int state) {// 滚动状态变化时调用}

**这里我们通过view Pager滑动时的监听来进行文本和小圆点的加载,通常这里我们选用onPageSelected()来加载,因为该方法是在新的条目被选中时调用,其他的两个方法的调用事件不满足条件,不能实现文字和小圆点的准确加载。
**接下来就是如何实现自动的轮播了,

// 开启轮询new Thread(){public void run() {isRunning = true;while(isRunning){try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}// 往下跳一位runOnUiThread(new Runnable() {@Overridepublic void run() {System.out.println("设置当前位置: " + viewPager.getCurrentItem());viewPager.setCurrentItem(viewPager.getCurrentItem()+1);                         }});}};}.start();

**要想实现定时的轮播,那么就要让线程sleep一定的时间,但是不能在主线程sleep,主线程等待,用户就无法进行操作,所以开辟一个子线程进行轮播,但是由于轮播又是已是一个需要刷新Ui的操作,那么我们就需要一个handler来接收刷新Ui的消息,在主线程中刷新UI,也可以通过上面这种方式来进行刷新UI的操作,通过runOnUiThread(new Runnable())的方法,开辟一个刷新UI线程,在这个线程中的run方法中刷新UI.
**好了,这就是一个简单的实现广告轮播图的View pager的实现方法。

这篇关于View pager实现自动轮播图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/568410

相关文章

C#借助Spire.XLS for .NET实现在Excel中添加文档属性

《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Python实现快速扫描目标主机的开放端口和服务

《Python实现快速扫描目标主机的开放端口和服务》这篇文章主要为大家详细介绍了如何使用Python编写一个功能强大的端口扫描器脚本,实现快速扫描目标主机的开放端口和服务,感兴趣的小伙伴可以了解下... 目录功能介绍场景应用1. 网络安全审计2. 系统管理维护3. 网络故障排查4. 合规性检查报错处理1.

Python轻松实现Word到Markdown的转换

《Python轻松实现Word到Markdown的转换》在文档管理、内容发布等场景中,将Word转换为Markdown格式是常见需求,本文将介绍如何使用FreeSpire.DocforPython实现... 目录一、工具简介二、核心转换实现1. 基础单文件转换2. 批量转换Word文件三、工具特性分析优点局

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位

Java使用Spire.Barcode for Java实现条形码生成与识别

《Java使用Spire.BarcodeforJava实现条形码生成与识别》在现代商业和技术领域,条形码无处不在,本教程将引导您深入了解如何在您的Java项目中利用Spire.Barcodefor... 目录1. Spire.Barcode for Java 简介与环境配置2. 使用 Spire.Barco

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求