无尽的循环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

总结

希望对大家有帮助。多提意见。

近段时间项目非常赶,非常长时间没看书写博客了。

赶项目赶得都麻,放松。偷偷懒。写博客是。

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-10-12 20:34:20

无尽的循环ViewPager的相关文章

Android循环ViewPager(二)

上午没事写了一篇,下午有事,晚上回来看看感觉写的差点意思,上篇文章大概的关于循环是自己添加了两个空的View,看到网上还有一种就是在自定义的Adapter中getCount中返回最大值,然后destroyItem不删除View,添加异常,说了这么多,我实验之后总是有问题,如果有弄成功的可以告知我一下,我的是三张图片~还是按照上午的那种方式就是第一个和最后一个是空View: 基础布局 看下效果吧,加了一排小圈圈,比上午的那个Demo好看: activity_pager.xml: <FrameLay

循环viewpager

如果viewpager listadapter小于三个.用这个移除异常. for (View view : viewList) {             ViewGroup p = (ViewGroup) view.getParent();             if (p != null) {                 p.removeAllViewsInLayout();             }         }

Handler+Timer/TimerTask实现ViewPager的自动循环播放

ViewPager是android.support.v4中提供的空间,和IOS中的UIScrollView有类似的效果,ViewPager正常工作需要一个PagerAdapter. PagerAdapter.java如下: package com.mxd.studyandroid; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import

东北育才 第4天

OIER的生活总是满足“一些好事,然后一些坏事,然后一些好事”这样的规律.所以OIER认为接下来的n天也是满足这样的规律的. 昨天崩了,这道题当时没有读懂,结果只有好事坏事好事三段,当时直接以为好事坏事好事坏事好事坏事是个无尽的循环.或许是一位挺像我的,因为又是一个rank 1. 确实不想说,坏的时候可以直接垫底,好友可以特别好,似乎从小到大一直是这样,让我特别懵. 今天晚上看了一部电影,潘菲洛夫28勇士,战争片,老毛子16年拍的,豆瓣评分7.1,据说耗资200万美元.几乎没有剧情,就是一个排的

JUnit(4)单元测试利器 JUnit 4

引言 毋庸置疑,程序员要对自己编写的代码负责,您不仅要保证它能通过编译,正常地运行,而且要满足需求和设计预期的效果.单元测试正是验证代码行为是否满足预期的有效手段之一.但不可否认,做测试是件很枯燥无趣的事情,而一遍又一遍的测试则更是让人生畏的工作.幸运的是,单元测试工具 JUnit 使这一切变得简单艺术起来. JUnit 是 Java 社区中知名度最高的单元测试工具.它诞生于 1997 年,由 Erich Gamma 和 Kent Beck 共同开发完成.其中 Erich Gamma 是经典著作

谈谈敏捷开发

我对敏捷开发是源于10多年前看了一本关于迭代开发的书,从而对迭代开发有了一些兴趣.从那时开始有了迭代开发的概念.随着项目经验的增加迭代的重要性也越发觉得明显.随后进入了提倡敏捷开发的公司,被迫式的接触了许多"敏捷开发",随着项目经历越来越多,慢慢的就开始有了更新的认识和想法. 但是在接触敏捷开发这个体系之前,自己有机会做一个项目,那个时候我开始将自己认为更有利于项目的管理工作做了一些应用,那个阶段我的主要做法是: 1.项目中开始划分更短的制品交互周期,而不是以前那样等待产品开发完毕后发

python 多线程探索

前面已经了解过了,python多线程效率较低的主要原因是存在GIL,即Global Interpreter Lock(全局解释器锁).这里继续详细的看下GIL的说明与如何避免GIL的影响,从而提高python多线程的执行效率.什么是GIL首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编译器例如GCC,INTEL C++,Visual C++等

聊一下Python的线程 &amp; GIL

再来聊一下Python的线程 参考这篇文章 https://www.zhihu.com/question/23474039/answer/24695447 简单地说就是作为可能是仅有的支持多线程的解释型语言(perl的多线程是残疾,PHP没有多线程),Python的多线程是有compromise的,在任意时间只有一个Python解释器在解释Python bytecode.Ruby也是有thread支持的,而且至少Ruby MRI是有GIL的. 首先要了解 GIL,全称 Global Interp

android源码大放送(实战开发必备),免费安卓demo源码,例子大全文件详细列表

免费安卓demo源码,例子大全文件详细列表 本列表源码永久免费下载地址:http://www.jiandaima.com/blog/android-demo 卷 yunpan 的文件夹 PATH 列表 卷序列号为 0000-73EC E:. │ jiandaima.com文件列表生成.bat │ 例子大全说明.txt │ 本例子永久更新地址~.url │ 目录列表2016.03.10更新.txt │ ├─前台界面 │ ├─3D标签云卡片热门 │ │ Android TagCloudView云标签