Android 图片轮播控件

转载请注明出处 http://blog.csdn.net/u011510784/article/details/49766099

为方便高效开发Android项目,推出Android开发常用控件系列,提高代码复用性,降低开发成本.

本文介绍的是Android项目中经常可以看到的广告位图片轮播控件,本文介绍的控件是基于网上的开源项目Viewflow写的.
如图:
图片轮播'

在ViewFlow项目中的轮播不支持从第一张图片向前滑到最后一张图片,还需要进行一些改动.先看一下这个控件项目中所使用到的类:



ViewFlow就是自定义轮播控件;CircleFlowIndicator是自定义的指示器控件;FlowIndicator是个接口,指示器控件继承次接口;因为此轮播控件显示的图片是从网络上获取来的,所以用到了图片加载框架ImageLoader,在MyApplication里面初始化了此框架.接下来挑一些细节讲解下:
首先看下MainActivity中的初始化控件:
	private void initData() {
		head_tv_content.setText("0");
		
		viewFlow.setmSideBuffer(urlsForNet.length);
		viewFlow.setFlowIndicator(CFIndic);
		viewFlow.setTimeSpan(3000);
		viewFlow.startAutoFlowTimer(); // 启动自动播放
		viewFlow.setAdapter(new CirculateAdapter(urlsForNet));
		viewFlow.setOnViewSwitchListener(new ViewSwitchListener() {
			@Override
			public void onSwitched(View view, int position) {
				head_tv_content.setText("第" + (position+1)+"张");
			}
		});
	}
setmSideBuffer是设置轮播图片的数量,在CirculateAdapter类中需要注意的地方是这个adapter类的getCount()方法返回了一个Integer.MAX_VALUE,以便可以保证viewFlow的循环,我们修改后的这个项目中getCount()()方法只需要返回正常position.

在ViewFlow类中它的流程是这样的:假如需要轮播的图片一共有三张,那么它会初始化4张图片,第四张放的就是第一张的图片:
                View currentView = makeAndAddView(position, true,(recycleViews.isEmpty() ? null : recycleViews.remove(0)));
		mLoadedViews.addLast(currentView);
		for (int offset = 1; mSideBuffer - offset >= 0; offset++) {
			int leftIndex = position - offset;
			int rightIndex = position + offset;
			if (leftIndex >= 0)
				mLoadedViews.addFirst(makeAndAddView(leftIndex,false,
								(recycleViews.isEmpty() ? null : recycleViews.remove(0))));
			if (rightIndex < mAdapter.getCount())
				mLoadedViews.addLast(makeAndAddView(rightIndex, true, </span>
<span style="font-family:SimHei;font-size:14px;">                                                                (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
		}
makeAndAddView()方法的作用是根据传入的position得到adapter中相应的view,即最终会调用 adapter.getView()方法来返回一个view.在for循环之前,先添加当前position对应的图片,因为当前position也可能不为0,然后再通过for循环在依次添加其他图片.额外的一张图片也是在这里添加的,因为mAdapter.getCount()返回到是Integer.MAX_VALUE,这里的mLoadedView集合用的是LinkedList<>,方便快速的插入与删除.到这里图片初始化完成,接下来是滑动,滑动的细节源代码写的很清楚就不在一一贴代码了,下面看他实现循环滚动的方法:
	private void postViewSwitched(int direction) {
		if (direction == 0)
			return;
		if (direction > 0) { // to the right
			mCurrentAdapterIndex++;
			mCurrentBufferIndex++;
			View recycleView = null;
			// Remove view outside buffer range
			if (mCurrentAdapterIndex > mSideBuffer) {
				recycleView = mLoadedViews.removeFirst();
				detachViewFromParent(recycleView);
				mCurrentBufferIndex--;
			}
			// Add new view to buffer
			int newBufferIndex = mCurrentAdapterIndex + mSideBuffer;
			if (newBufferIndex < mAdapter.getCount())
				mLoadedViews.addLast(makeAndAddView(newBufferIndex, true,
						recycleView));

		} else { // to the left
			mCurrentAdapterIndex--;
			mCurrentBufferIndex--;
			View recycleView = null;
			// Remove view outside buffer range
			if (mAdapter.getCount() - 1 - mCurrentAdapterIndex > mSideBuffer) {
				recycleView = mLoadedViews.removeLast();
				detachViewFromParent(recycleView);
			}
			// Add new view to buffer
			int newBufferIndex = mCurrentAdapterIndex - mSideBuffer;
			if (newBufferIndex > -1) {
				mLoadedViews.addFirst(makeAndAddView(newBufferIndex, false,
						recycleView));
				mCurrentBufferIndex++;
			}
		}
		requestLayout();
		setVisibleView(mCurrentBufferIndex, true);
		if (mIndicator != null) {
			mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
					mCurrentAdapterIndex);
		}
		if (mViewSwitchListener != null) {
			mViewSwitchListener
					.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
							mCurrentAdapterIndex);
		}
	}

这个方法中传入的是滑动的方向,他的判断方式是记录当前页面,计算将要滑动的下一个页面,如果将要滑动的页面号减去当前页面号大于0,那么认为是正方向,小于0则是反方向.如果是正方向
判断当前图片页面的索引值是否大于了轮播控件中图片的张数,因为这个mLoadedView集合里存放的图片张数比轮播控件里的实际张数大一.如果大于了,说明已经滑动到mLoadedView集合的最后一张,也就是实际图片的第一张了,那么就把mLoadedView集合的第一张去掉,新加一张图片,也就是实际图片的第二张,方向相反一个道理.这样就实现了图片的轮播,但是这样在显示第一张图片的情况下是不能滑动到最后一张的,接下来我们修改一下.

大体流程是这样的:初始化这个轮播控件的时候,在mLoadedView集合里面多加两个图片,即在最前面加一张最后那个图片,在最后面加一张第一张那个图片,原来是1,2,3 现在是 3_,1,2,3,1_. 在滑动到1_时候把相应的位置重置成1,将图片也滑动到1位置,一个道理,当向后滑到3_时,将其信息重置成3,这样在第一张图片的情况下也可以向后滑动了.
	private void postViewSwitched(int direction) {
		if (direction == 0)
			return;
		if (direction > 0) { // to the right
			if (mCurrentScreen == mSideBuffer + 1) {
				mCurrentAdapterIndex = -1;
				mCurrentBufferIndex = 0;
				mCurrentScreen = 1;
			}
			mCurrentAdapterIndex++;
			mCurrentBufferIndex++;

		} else { // to the left
			if (mCurrentScreen == 0) {
				mCurrentAdapterIndex = mSideBuffer;
				mCurrentBufferIndex = mSideBuffer + 1;
				mCurrentScreen = mSideBuffer;
			}
			mCurrentAdapterIndex--;
			mCurrentBufferIndex--;

		}
		requestLayout();
		setVisibleView(mCurrentBufferIndex, true);
		if (mIndicator != null) {
			mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
					mCurrentAdapterIndex);
		}
		if (mViewSwitchListener != null) {
			mViewSwitchListener
					.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
							mCurrentAdapterIndex);
		}
	}
当然里面还有很多的细节处理,具体见源码吧!






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值