无限循环的ViewPager

目前情况

在不修改源码的情况下,当ViewPager滑动到最后一个item的时候,他就无法再往右滑动;当ViewPager滑动到第一个item的时候,他也无法再往前滑动。(以上全是废话)

设想

我们可以这样想,当滑动到最后一个的时候,我们让他跳转到第一个,这样他就可以继续往后滑动了,这样就达到了我们想要的循环滑动。

虽然功能上是循环了,但是实际显示的时候会在最后一个和第一个之间自动跳转。

优化

我们可以在原来的链表中首尾各增加一个假的item,用多余的两个item来作跳转的动作,这样就可以避免出现自动跳转的错误画面了。

我们要显示的是下面ABC画面,位置分别是012.

 

 

 

 

实际上,我们添加数据的时候,多添加了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

 

总结

希望对大家有帮助,多提意见。近段时间项目很赶,很长时间没看书写博客了。赶项目赶得都麻木了,放松放松,偷偷懒,写写博客吧。

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: ViewPager和ViewPager2都是Android中的视图控件,用于实现滑动切换不同页面的功能。 ViewPager是Android SDK中的一个类,它可以在同一个Activity中展示多个Fragment,通过左右滑动来切换不同的Fragment。ViewPager可以实现无限循环滑动,但是它的性能不够好,存在一些问题,比如在嵌套使用时会出现滑动冲突等。 ViewPager2是ViewPager的升级版,它是在AndroidX库中的一个类,它解决了ViewPager存在的一些问题,比如滑动冲突、性能问题等。ViewPager2支持嵌套滑动,可以实现更加灵活的布局,同时还支持横向和纵向滑动。因此,ViewPager2是更加推荐使用的视图控件。 ### 回答2: ViewPager 和 ViewPager2 都是 Android 平台上的视图容器,它们都用于实现左右滑动切换多个视图的效果。不过,它们也有一些不同的特点。 ViewPager 是 Android 系统自带的视图容器,它主要用于在同一个 Activity 中切换多个 Fragment。ViewPager 会将多个 Fragment 放置在同一个视图中,通过滑动切换 Fragment 来实现左右滑动的效果。ViewPager 比较易用、稳定,使用起来也比较简单,但是在一些功能上有一定的局限性。 ViewPager2 是 ViewPager 的升级版,它是在 AndroidX 中新增加的一个控件。相较于 ViewPager,ViewPager2 有一些更加高级和灵活的功能。首先,ViewPager2 支持 RecyclerView.Adapter,这样用户可以通过 RecyclerView.Adapter 来实现 ViewPager2 中的数据管理,这大大提高了数据操作的灵活性。其次,ViewPager2 支持垂直滑动的效果,这使得用户可以通过上下滑动切换多个视图。此外,ViewPager2 还支持滑块(PageTransformer)和视图预加载(OffscreenPageLimit)等高级功能,让用户可以更加方便地自定义 ViewPager2 的效果和行为。 总的来说,如果只是想要简单实现左右滑动切换多个 Fragment 的效果,可以使用 ViewPager。如果需要更加高级、灵活的功能,或者需要在 ViewPager 中嵌套 RecyclerView 或其他视图控件,则可以选择 ViewPager2。同时,最好在使用 ViewPager2 时,将所有 Fragment 替换为 RecyclerView,这样能够充分利用 ViewPager2 的强大功能。 ### 回答3: ViewPager和ViewPager2是Android平台上常用的 View容器 组件。它们最主要的作用是管理多个子view的滑动显示,类似于滑动的页面。 ViewPager从Android API Level 11就被引入,它支持从左往右滑动查看多个子视图,以轻松实现流畅的“屏幕滑动”效果,常见的使用场景包括相册、图库、图片轮播图等。在使用ViewPager时,开发者需要自己实现适配器,根据需要返回子View。且ViewPager中每个页面的宽度是相等的,无法进行自由的布局。 而ViewPager2是新增的一个组件,它是AndroidX中的一部分,于2019年发布。ViewPager2相对于ViewPager的最大改进就在于支持不同宽度的页面。除了滑动方向以外,ViewPager2还支持从RecyclerView中使用适配器,从而不仅仅可以使用View,还可以使用任何RecyclerView的特性和布局(如GridLayoutManager等)。另一个重要的改进是支持了多层嵌套,并且同步了更多的触摸事件,增强了原生的滑动手势支持。 总之,ViewPager2是ViewPager的升级版,它具有更多灵活的布局和更好的性能。开发者可以根据自己的需求选择使用ViewPager或ViewPager2,相信在未来的Android开发中,ViewPager2会成为首选。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是MTT

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值