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

相关文章

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

MySQL8.0设置redo缓存大小的实现

《MySQL8.0设置redo缓存大小的实现》本文主要在MySQL8.0.30及之后版本中使用innodb_redo_log_capacity参数在线更改redo缓存文件大小,下面就来介绍一下,具有一... mysql 8.0.30及之后版本可以使用innodb_redo_log_capacity参数来更改

shell脚本自动删除30天以前的文件(最新推荐)

《shell脚本自动删除30天以前的文件(最新推荐)》该文章介绍了如何使用Shell脚本自动删除指定目录下30天以前的文件,并通过crontab设置定时任务,此外,还提供了如何使用Shell脚本删除E... 目录shell脚本自动删除30天以前的文件linux按照日期定时删除elasticsearch索引s

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque