无限循环的ViewPager
目前情况
在不修改源码的情况下,当ViewPager滑动到最后一个item的时候,他就无法再往右滑动;当ViewPager滑动到第一个item的时候,他也无法再往前滑动。(以上全是废话)
设想
我们可以这样想,当滑动最后一个的时候,我们让他跳转到第一个,这样他就可以继续往后滑动了,这样做行程了我们想要的循环滑动。
如果这样作,虽然功能上是循环了,但是实际显示的时候会在最后一个和第一个之间自动跳转。
优化
我们可以在原来的链表中首尾各增加一个假的item,用多余的两个item来作跳转的动作,这样就可以避免出现自动跳转的错误画面了。请看下面演示。
我们要显示的是下面A、B、C画面,位置分别是0、1、2.
实际上,我们添加数据的时候,多添加了2个。在位置0添加了最后一个界面C,在位置4添加了第一个界面A。
当界面滑动到位置3的时候,他还可以往右滑动,这样给人的感觉就是循环的。但,当滑动到位置4的时候,他右边没有了,这样岂不是露馅了?所以,当滑动到位置4的时候,立刻跳转到位置1。因为他们是同样的数据,所以从显示效果是看不出跳转了的,这样实际上我们就变成了位置1,这样就又可以继续往右滑动了。
重复上面条件的判断,这样就实现了往右的循环,往左也是同样的道理。
代码分析
在onPageSelected里面做条件判断,在onPageScrollStateChanged里面做跳转。关键代码如下:
初始化,首尾各增加一个item。
- // 增加第1个界面,实际上他显示的是最后一个界面
- addTextView(POINT_LENGTH - 1);
- // 增加实际显示的2、3、4界面
- for (int i = 0; i < 3; i++) {
- addTextView(i);
- addPoint(i);
- }
- // 增加最后的第5个界面,实际上他显示的是第一个界面
- addTextView(0);
条件判断:
- @Override
- public void onPageSelected(int pPosition) {
- mIsChanged = true;
- if (pPosition > POINT_LENGTH) {
- mCurrentPagePosition = FIRST_ITEM_INDEX;
- } else if (pPosition < FIRST_ITEM_INDEX) {
- mCurrentPagePosition = POINT_LENGTH;
- } else {
- mCurrentPagePosition = pPosition;
- }
- Log.i(TAG,"当前的位置是"+mCurrentPagePosition);
- setCurrentDot(mCurrentPagePosition);
- }
跳转:
- @Override
- public void onPageScrollStateChanged(int pState) {
- if (ViewPager.SCROLL_STATE_IDLE == pState) {
- if (mIsChanged) {
- mIsChanged = false;
- mViewPager.setCurrentItem(mCurrentPagePosition, false);
- }
- }
- }
完整的逻辑如下:
- package com.ahacool.circleviewpager;
- import java.util.ArrayList;
- import android.app.Activity;
- import android.os.Bundle;
- import android.support.v4.view.PagerAdapter;
- import android.support.v4.view.ViewPager;
- import android.support.v4.view.ViewPager.OnPageChangeListener;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ImageView;
- import android.widget.LinearLayout.LayoutParams;
- import android.widget.TextView;
- /**
- * @ClassName MainActivity
- * @Description 循环滑动viewpager的一种方法,滑动很流畅。实现方法:在实际显示的界面头和尾分别增加一个界面。
- * @author Moto
- * @date 2014 2014-7-18
- *
- */
- public class MainActivity extends Activity implements OnPageChangeListener {
- private ViewPager mViewPager;
- private ViewGroup mPointViewGroup;
- private ArrayList<View> mViewPagerList;
- private boolean mIsChanged = false;
- private int mCurrentPagePosition = FIRST_ITEM_INDEX;
- private int mCurrentIndex;
- private static final int POINT_LENGTH = 3;
- private static final int FIRST_ITEM_INDEX = 1;
- private static final String TAG = "MOTO";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initUI();
- }
- private void initUI() {
- mViewPager = (ViewPager) findViewById(R.id.viewpager);
- mPointViewGroup = (ViewGroup) findViewById(R.id.point_layout);
- mViewPagerList = new ArrayList<View>();
- // 增加第1个界面,实际上他显示的是最后一个界面
- addTextView(POINT_LENGTH - 1);
- // 增加实际显示的2、3、4界面
- for (int i = 0; i < 3; i++) {
- addTextView(i);
- addPoint(i);
- }
- // 增加最后的第5个界面,实际上他显示的是第一个界面
- addTextView(0);
- PagerAdapter pagerAdapter = new CustomPagerAdapter(mViewPagerList);
- mViewPager.setAdapter(pagerAdapter);
- mViewPager.setOnPageChangeListener(this);
- mViewPager.setCurrentItem(mCurrentPagePosition, false);
- }
- private void addTextView(int pIndex) {
- TextView textview = new TextView(this);
- textview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- textview.setGravity(Gravity.CENTER);
- textview.setText("这是第" + (pIndex + 1) + "个页面");
- textview.setTextSize(50);
- mViewPagerList.add(textview);
- }
- private void addPoint(int pIndex) {
- ImageView pointImageView = new ImageView(this);
- LayoutParams layoutParams = new LayoutParams(20, 20);
- layoutParams.setMargins(10, 0, 10, 0);
- pointImageView.setLayoutParams(layoutParams);
- pointImageView.setBackgroundResource(R.drawable.point_style);
- if (0 == pIndex) {
- pointImageView.setEnabled(false);
- }
- mPointViewGroup.addView(pointImageView);
- }
- private void setCurrentDot(int positon) {
- // 界面实际显示的序号是第1, 2, 3。而点的序号应该是0, 1, 2.所以减1.
- positon = positon - 1;
- if (positon < 0 || positon > mViewPagerList.size() - 1 || mCurrentIndex == positon) {
- return;
- }
- mPointViewGroup.getChildAt(positon).setEnabled(false);
- mPointViewGroup.getChildAt(mCurrentIndex).setEnabled(true);
- mCurrentIndex = positon;
- }
- @Override
- public void onPageScrollStateChanged(int pState) {
- if (ViewPager.SCROLL_STATE_IDLE == pState) {
- if (mIsChanged) {
- mIsChanged = false;
- mViewPager.setCurrentItem(mCurrentPagePosition, false);
- }
- }
- }
- @Override
- public void onPageScrolled(int arg0, float arg1, int arg2) {
- }
- @Override
- public void onPageSelected(int pPosition) {
- mIsChanged = true;
- if (pPosition > POINT_LENGTH) {
- mCurrentPagePosition = FIRST_ITEM_INDEX;
- } else if (pPosition < FIRST_ITEM_INDEX) {
- mCurrentPagePosition = POINT_LENGTH;
- } else {
- mCurrentPagePosition = pPosition;
- }
- Log.i(TAG,"当前的位置是"+mCurrentPagePosition);
- setCurrentDot(mCurrentPagePosition);
- }
- }
源码下在地址:https://github.com/bird7310/Demos.git
总结
希望对大家有帮助,多提意见。近段时间项目很赶,很长时间没看书写博客了。赶项目赶得都麻木了,放松放松,偷偷懒,写写博客吧。
无限循环的ViewPager的更多相关文章
- android 无限循环的viewpager
思路 例如存在 A -B -C 需要在viewpager滑动时无限循环 1.我们可以设计 C' A B C A' C'与C相同,A'与A相同 2.滑动到A'时,则index回到1 3.滑动到C'时, ...
- [android] 轮播图-无限循环
实现无限循环 在getCount()方法中,返回一个很大的值,Integer.MAX_VALUE 在instantiateItem()方法中,获取当前View的索引时,进行取于操作,传递进来的int ...
- 详细分析Android viewpager 无限循环滚动图片
由于最近在忙于项目,就没时间更新博客了,于是趁着周日在房间把最近的在项目中遇到的技术总结下.最近在项目中要做一个在viewpager无限滚动图片的需求,其实百度一下有好多的例子,但是大部分虽然实现了, ...
- 一行代码引入 ViewPager 无限循环 + 页码显示
(出处:http://www.cnblogs.com/linguanh) 前序: 网上的这类 ViewPager 很多,但是很多都不够好,体现在 bug多.对少页面不支持,例如1~2张图片.功能整合不 ...
- ViewPager,实现真正的无限循环(定时+手动)
利用定时器,实现循环轮播,很简单:只需在定时器的消息里加如下代码即可: int count = adapter.getCount(); if (count > 1) { // 多于1个,才循环 ...
- 扩展ViewFlow避免和ViewPager滑动冲突,同时支持无限循环,并完美和CircleFlowIndicator结合
首先,为了避免滑动冲突,我们要继承ViewFlow,重写onInterceptTouchEvent public class MyViewFlow extends ViewFlow { private ...
- 自定义完美的ViewPager 真正无限循环的轮播图
网上80%的思路关于Android轮播图无限循环都是不正确的,不是真正意义上的无限循环, 其思路大多是将ViewPager的getCount方法返回值设置为Integer.MAX_VALUE, 然后呢 ...
- android 自定义无限循环播放的viewPager。轮播ViewPager。实现循环播放 广告,主题内容,活动,新闻内容时。
前言 实际项目需要一个 播放广告的控件,可能有多个广告图片.每个一段时间更换该图片.简单来说,就是一个 “循环播放图片”的控件. 间隔时间更换图片 一般来说,图片切换时需要有动画效果 需要支持手势,用 ...
- ViewPager 无限循环
Overview 我们在使用ViewPager来制作图片轮播的时候,常常为ViewPager不能一直无限循环的问题所苦恼.对于这个问题,目前从网上找到了两个思路来解决: 将 ViewPager 的Co ...
随机推荐
- MySQL被Oracle并购后的409个日日夜夜
2009年4月20日,Oracle并购了Sun,这也意味着MySQL归属到甲骨文的旗下.四百多天过去了,究竟这场并购结局如何?请看本文. 去年对Sun的收购,让甲骨文顺利的将一个潜在的对手MySQL收 ...
- 简单总结焦点事件、Event事件对象、冒泡事件
每学习一些新的东西,要学会复习,总结和记录. 今天来简单总结一下学到的几个事件:焦点事件.Event事件对象.冒泡事件 其实这几个事件应该往深的说是挺难的,但今天主要是以一个小菜的角度去尝试理解一些基 ...
- memset 初始化数组
memset是初始化一段内存区域的函数,其头文件是<string.h>,以前经常使用出现错误,整理一下. C++ Reference对于memset的定义为: void * memset ...
- 【COGS1049】天空中的繁星
[题目背景] 第二届『Citric』杯NOIP提高组模拟赛 第二题 [题目描述] Lemon最近买了一台数码相机.某天Lemon很无聊,于是对着夜空拍了一张照片,然后把照片导入了电脑.Lemon想依靠 ...
- 浮点与整形在GUI下的相关思考
平时不接触绘图,似乎感觉不到浮点和整形所带来的区别,这次项目中意外的碰到了浮点与整形进行迁移的工作.因此写点心得,让自己以后也可以看看. 用浮点作图有个最大的弊端就是边界情况,比如你需要在点(20,2 ...
- System.InvalidOperationException: 无法加载协定为“ServiceReference1.XXXXXXXXXXXXXXXX”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分。
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="testWeb ...
- Destoon QQ互联一键登录审核不通过的解决方案
在QQ互联上申请帐号之后提交了审核, 后台填写APPID和KEY之后自己申请的QQ号可以正常登录,但QQ互联审核的时候一直审核不通过说是“您的网站审核未通过,原因是“点击QQ登录按钮提示登录失败或出现 ...
- Python新手学习基础之数据结构-对数据结构的认知
什么是数据结构? 数据结构是指:相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成. 举个列子来理解这个数据结构: 数据可以比作是书本, 数据结构相当于书架,书存放在书架上, ...
- Javascript图片轮播
原文链接:http://www.imooc.com/article/7393 编辑HTML代码: <div id="wrap"><!--图片展示区--> & ...
- IPv6-only 的兼容性解决方案-b
前几天Apple宣布 6月1日后所有应用必须支持IPv6-only网络 今天抽空看了下这方面的知识 首先解释下IPv6的是什么? 维基百科的定义如下:IPv6是Internet Protocol ve ...