Viewpager实现了左右循环滚动,但是无法实现类似网易新闻的循环滚动效果。所以,就自己简单写了一个。
原理:
1.在ViewPager的第一页,插入最后一页的内容。在最后一页,插入原本第一页的内容。
如:原本内容页为A、B、C,则添加后页签内容为 C、A、B、C、A。
2.当从当前的第1页,右滑进入第0页后,迅速将页面切为倒数第二页。
当从当前的倒数第二页,左滑进入最后一页后,迅速将页面切为倒数第1页。
如:从第一个A,切到C,则页面迅速切换到最后一个C。
具体实现:
1.先看ViewPagerAdapter的3个方法:
getCount() :指示页签的个数
此处我们在原来的基础上+2
destroyItem(View container, int position, Object object):当页签变化时,销毁指定位置的界面
这里我们选择只销毁中间的界面
instantiateItem(View container, int position): 当页签变化时,加载指定位置的界面
此处做逻辑上的处理,当position为0时,加载最后一页。posiiton为最大时,加载第一页
public class PhotoNewsViewPagerAdapter extends PagerAdapter {
private ArrayList<View> views = new ArrayList<View>();
private List<Article> mData = new ArrayList<Article>();
private Context mContext;
public PhotoNewsViewPagerAdapter() {
// TODO Auto-generated constructor stub
}
public void setData(Context context,List<Article> data) {
mContext = context;
mData.clear();
mData.addAll(data);
LayoutInflater inflater = LayoutInflater.from(context);
views.clear();
for(Article article:mData){
View view = inflater.inflate(R.layout.activity_news_viewpager_item, null);
views.add(view);
ImageView image = (ImageView) view.findViewById(R.id.iv_photo);
image.setOnClickListener(new OnImageClickListener(article));
showPhoto(image, article);
TextView title = (TextView) view.findViewById(R.id.tv_title);
title.setText(article.getTitle());
}
}
public List<Article> getData() {
return mData;
}
@Override
public int getCount() {
return views.size()+2;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
@Override
public void destroyItem(View container, int position, Object object) {
if(position>1&&position<views.size()){
((ViewPager) container).removeView(views.get(getPosition(position)));
}
}
@Override
public Object instantiateItem(View container, int position) {
try {
((ViewPager) container).addView(views.get(getPosition(position)));
} catch (Exception e) {
// TODO: handle exception
}
return views.get(getPosition(position));
}
private int getPosition(int position){
int count = views.size();
if(position==0){
return count-1;
}else if(position==count+1){
return 0;
}else{
return position-1;
}
}
/**
* 显示图片
* @param view 显示的view
* @param newsBean 新闻对象
*/
private void showPhoto(ImageView view, Article newsBean) {
String photoPath = SystemUtil.getPhotoUrl(mContext, newsBean.getPhotoPath());
// 如果有图片,则显示
//配置图片加载及显示选项(还有一些其他的配置,查阅doc文档吧)
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_empty) //在ImageView加载过程中显示图片
.showImageForEmptyUri(R.drawable.ic_empty) //image连接地址为空时
.showImageOnFail(R.drawable.ic_empty) //image加载失败
.cacheInMemory(true) //加载图片时会在内存中加载缓存
.cacheOnDisc(true) //加载图片时会在磁盘中加载缓存
.displayer(new RoundedBitmapDisplayer(1)) //设置用户加载图片task(这里是圆角图片显示)
.build();
// 图片加载器
ImageLoader imageLoader = ImageLoader.getInstance();
// 图片加载监听事件
ImageLoadingListener animateFirstListener = new SimpleImageLoadingListener();
//先在加载前显示默认图片
imageLoader.displayImage("", view, options, animateFirstListener);
//加载缩略图
imageLoader.displayImage(photoPath, view, options, animateFirstListener);
}
private class OnImageClickListener implements OnClickListener{
private Article article;
public OnImageClickListener(Article article) {
this.article = article;
}
@Override
public void onClick(View v) {
}
};
}
indicator.setOnPageChangeListener(new OnPageChangeListener() {
//当前的索引
private int currentIndex = 1;
@Override
public void onPageSelected(int arg0) {
currentIndex = arg0;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
//滑动停止后,再切换,效果会好一点
if(arg0 == 0){
if(currentIndex==0){
viewPager.setCurrentItem(photoAdapter.getCount()-2, false);
}else if(currentIndex==photoAdapter.getCount()-1){
viewPager.setCurrentItem(1, false);
}
}
}
});
至此,ViewPager循环切换就做好了,接下来就是底部页签指示标志的修改。
3.由于我们多加了两个页面,导致CirclePageIndicator显示的时候会多两个点,所以要修改其源码。
增加mIsLoopViewPager 属性,兼容循环ViewPager。
修改下面的代码,把第一个和最后一个点,屏蔽掉。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
//Draw stroked circles
int startIndex = 0;
int endIndex = count;
if(mIsLoopViewPager){
startIndex = 1;
endIndex = count-1;
}
for (int iLoop = startIndex; iLoop < endIndex; iLoop++) {
float drawLong = longOffset + (iLoop * threeRadius);
if (mOrientation == HORIZONTAL) {
dX = drawLong;
dY = shortOffset;
} else {
dX = shortOffset;
dY = drawLong;
}
// Only paint fill if not completely transparent
if (mPaintPageFill.getAlpha() > 0) {
canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
}
// Only paint stroke if a stroke width was non-zero
if (pageFillRadius != mRadius) {
canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
}
}
...
}
对CirclePageIndicator不清楚的,参考 http://my.oschina.net/u/1403288/blog/208402
收工。