Android简单实现无限滚动自动滚动的ViewPager

经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的ViewPager

效果如下:

简单的说一下实现思路,要实现无限滚动的话就要在PagerAdapter上面做一些手脚,在PagerAdapter的getCount的函数的返回值设置成Integer.MXA_VALUE就可以实现向右无限滚动,但是要实现向左无限滚动呢?就是一开始的时候setCurrentItem的时候设置一个非常大的值(大到你向左滚动了一万年还是有东西)

@Override public int getCount() { return Integer.MAX_VALUE; } mPager.setCurrentItem(10000 * mDatas.size());//一开始设置成这样的话就可以向左无限滚动了

然后另外一个就是底部的游标了:

底部的游标是用一个自定义视图:无非就是画一个背景,然后在画一个高亮的游标

/** * 指示游标 */ private class TipView extends View { private int mPadding; private int mCount; private int mCurPos; private Paint mNorPaint;//未被选中的颜色 private Paint mSelPaint;//被选中的颜色 白色 private int mHeight; public TipView(Context context, int count) { super(context); mNorPaint = new Paint(); mNorPaint.setAntiAlias(true); int selHeight = ShowUtils.dip2px(2); int norHeight = ShowUtils.dip2px(1); mHeight = ShowUtils.dip2px(2); mNorPaint.setStrokeWidth(norHeight); mNorPaint.setColor(Color.argb(80, 255, 255, 255)); mSelPaint = new Paint(); mSelPaint.setAntiAlias(true); mSelPaint.setStrokeWidth(selHeight); mSelPaint.setColor(Color.WHITE); mCount = count; mPadding = ShowUtils.dip2px(0); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int ow = (getWidth()-2 * mPadding)/ mCount; int y = getHeight() / 2; canvas.drawLine(mPadding, y, mCurPos * ow + mPadding, y, mNorPaint); canvas.drawLine(mCurPos * ow + mPadding, y, (mCurPos + 1) * ow + mPadding, y, mSelPaint); canvas.drawLine((mCurPos + 1) * ow + mPadding, y, getWidth() - mPadding, y, mNorPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ViewGroup.LayoutParams vp = getLayoutParams(); vp.width = ViewGroup.LayoutParams.MATCH_PARENT; vp.height = mHeight; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public void setCurPostion(int pos) { mCurPos = pos; invalidate(); } public void setCount(int count) { mCount = count; } }

R.layout.layout_recommend_item的布局:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_pic" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@null" android:scaleType="fitXY"/> <LinearLayout android:layout_width="match_parent" android:layout_height="48dp" android:orientation="vertical" android:layout_alignParentBottom="true" android:background="@drawable/recommend" android:gravity="center"> <TextView android:id="@+id/tv_desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/white" android:textSize="@dimen/text_normal" android:maxLines="1" android:ellipsize="end" android:shadowColor="#ff333333" android:shadowDx="2" android:shadowDy="2" android:paddingRight="8dp" android:paddingLeft="8dp" android:shadowRadius="1" /> </LinearLayout> </RelativeLayout>

还有一个是实现自动滚动,自动滚动的话就是监听OnPagerChangeListener里面的函数,在ViewPager状态改变的时候利用Handler发送一个切换界面的消息:

@Override public void onPageScrollStateChanged(int i) { curState = i; if(i == ViewPager.SCROLL_STATE_DRAGGING){ //viewpager正在被拖动的时候 stopAnimation(); }else { //没有可执行消息时候添加消息 实现自动滚动 if(!(sHandler.hasMessages(START_SCROLL)&&sHandler.hasMessages(SCROLL_NEXT))){ startAnimation(); } } } @Override public void onPageSelected(final int i) { //页面跳转后得到调用 sHandler.removeMessages(SCROLL_NEXT); sHandler.removeMessages(START_SCROLL); if(curState == ViewPager.SCROLL_STATE_DRAGGING){ return; } Message msg = sHandler.obtainMessage(SCROLL_NEXT); msg.arg1 = i + 1; msg.obj = mPager; sHandler.sendMessageDelayed(msg, SHOW_TIME); mTipView.setCurPostion(i % mDatas.size()); }

整体的代码:

import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.papau.show.R; import com.papau.show.entity.HeadViewEntity; import com.papau.show.utils.ShowUtils; import java.util.ArrayList; import java.util.List; public class RecommendView extends RelativeLayout implements IRecommend { private static final int START_SCROLL = 1; private static final int SCROLL_NEXT = 2; private static final int SHOW_TIME = 5000; private List<HeadViewEntity> mDatas = new ArrayList<>(); private ViewPager mPager; private Context mContext; private int mWidth, mHeight; private ImageLoader mLoader; private DisplayImageOptions mOptions; private int mTitleHeight; private TipView mTipView; private static Handler sHandler = new Handler() { @Override public void handleMessage(Message msg) { int w = msg.what; ViewPager pager = (ViewPager) msg.obj; switch (w) { case START_SCROLL: pager.setCurrentItem(msg.arg1, true); break; case SCROLL_NEXT: pager.setCurrentItem(msg.arg1, true); break; } } }; public RecommendView(Context context) { super(context); } public RecommendView(Context context, int w, int h) { super(context); mContext = context; mWidth = w; mHeight = h; initView(); // mPager.setAdapter(new RecommendAdapter()); mPager.setOnPageChangeListener(new MOnPagerChangeListener()); mLoader = ImageLoaderManager.getImageLoader(mContext); mOptions = ImageLoaderManager.getCacheOnDiskOptions(mContext); init(); // DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); mTitleHeight = ShowUtils.dip2px(48);//设置游标高度 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ViewGroup.LayoutParams vp = getLayoutParams(); if (vp != null) { //设置视图的宽高 vp.width = mWidth; vp.height = mHeight; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private void initView() { mPager = new ViewPager(mContext); RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); addView(mPager, rp); } /** * 初始化指示游标 */ private void initTipView() { if (mTipView == null) { RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(10, 10); rp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);//显示在父控件的底部 rp.bottomMargin = mTitleHeight;//游标的高度 mTipView = new TipView(mContext, mDatas.size()); addView(mTipView, rp); } else { mTipView.setCount(mDatas.size()); } } @Override public void upDate() { getData(); } @Override public void init() { getData(); } @Override public void startAnimation() { if (mDatas.size() == 0) { return; } Message msg = sHandler.obtainMessage(START_SCROLL); msg.obj = mPager; msg.arg1 = (mPager.getCurrentItem() + 1); sHandler.sendMessageDelayed(msg, SHOW_TIME); } @Override public void stopAnimation() { sHandler.removeMessages(START_SCROLL); sHandler.removeMessages(SCROLL_NEXT); } /** * 获取viewpager要显示的数据 */ private void getData() { String[] imageData = new String[]{"http://f.hiphotos.baidu.com/image/h%3D360/sign=e105b9f1d61b0ef473e89e58edc651a1/b151f8198618367a9f738e022a738bd4b21ce573.jpg", "http://c.hiphotos.baidu.com/image/h%3D360/sign=b8cea9e92b738bd4db21b437918b876c/f7246b600c3387448982f948540fd9f9d72aa0bb.jpg", "http://a.hiphotos.baidu.com/image/h%3D360/sign=3da95d01e7dde711f8d245f097eecef4/71cf3bc79f3df8dc39cb6295cf11728b461028c4.jpg", "http://d.hiphotos.baidu.com/image/h%3D360/sign=410c3c96a60f4bfb93d09852334f788f/10dfa9ec8a136327a1de913a938fa0ec08fac78c.jpg", "http://e.hiphotos.baidu.com/image/h%3D360/sign=f6600b1613dfa9ece22e501152d1f754/342ac65c10385343ff41ee2b9113b07eca808829.jpg"}; for (int i = 0; i < 5; i++) { HeadViewEntity info = new HeadViewEntity(); info.setImageUrl(imageData[i]); info.setTitle("我不做大哥好多年"+i); info.setUrl("www.baidu.com"); mDatas.add(info); } sHandler.postDelayed(new Runnable() { @Override public void run() { stopAnimation(); initTipView(); mPager.setAdapter(new RecommendAdapter()); mPager.setCurrentItem(10000 * mDatas.size());//一开始设置成这样的话就可以向左无限滚动了 } },2000); } /** * viewpager子项内容 */ private class RecommendAdapter extends PagerAdapter { /** * 填充子项视图的内容 * @param container 父控件 viewpager * @param position 子项的位置 * @return 返回子项视图 */ @Override public Object instantiateItem(ViewGroup container, int position) { int curPos = position % mDatas.size(); View view = View.inflate(mContext, R.layout.layout_recommend_item, null); ViewGroup.LayoutParams vp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ImageView iv = (ImageView) view.findViewById(R.id.iv_pic); TextView tv = (TextView) view.findViewById(R.id.tv_desc); tv.setText(mDatas.get(curPos).getTitle()); mLoader.displayImage(mDatas.get(curPos).getImageUrl(), iv, mOptions); container.addView(view, vp); view.setTag(curPos); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } } private class MOnPagerChangeListener implements ViewPager.OnPageChangeListener { private int curState; @Override public void onPageScrolled(int i, float v, int i1) { } @Override public void onPageScrollStateChanged(int i) { curState = i; if(i == ViewPager.SCROLL_STATE_DRAGGING){ //viewpager正在被拖动的时候 stopAnimation(); }else { //没有可执行消息时候添加消息 实现自动滚动 if(!(sHandler.hasMessages(START_SCROLL)&&sHandler.hasMessages(SCROLL_NEXT))){ startAnimation(); } } } @Override public void onPageSelected(final int i) { //页面跳转后得到调用 sHandler.removeMessages(SCROLL_NEXT); sHandler.removeMessages(START_SCROLL); if(curState == ViewPager.SCROLL_STATE_DRAGGING){ return; } Message msg = sHandler.obtainMessage(SCROLL_NEXT); msg.arg1 = i + 1; msg.obj = mPager; sHandler.sendMessageDelayed(msg, SHOW_TIME); mTipView.setCurPostion(i % mDatas.size()); } } /** * 指示游标 */ private class TipView extends View { private int mPadding; private int mCount; private int mCurPos; private Paint mNorPaint;//未被选中的颜色 private Paint mSelPaint;//被选中的颜色 白色 private int mHeight; public TipView(Context context, int count) { super(context); mNorPaint = new Paint(); mNorPaint.setAntiAlias(true); int selHeight = ShowUtils.dip2px(2); int norHeight = ShowUtils.dip2px(1); mHeight = ShowUtils.dip2px(2); mNorPaint.setStrokeWidth(norHeight); mNorPaint.setColor(Color.argb(80, 255, 255, 255)); mSelPaint = new Paint(); mSelPaint.setAntiAlias(true); mSelPaint.setStrokeWidth(selHeight); mSelPaint.setColor(Color.WHITE); mCount = count; mPadding = ShowUtils.dip2px(0); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int ow = (getWidth()-2 * mPadding)/ mCount; int y = getHeight() / 2; canvas.drawLine(mPadding, y, mCurPos * ow + mPadding, y, mNorPaint); canvas.drawLine(mCurPos * ow + mPadding, y, (mCurPos + 1) * ow + mPadding, y, mSelPaint); canvas.drawLine((mCurPos + 1) * ow + mPadding, y, getWidth() - mPadding, y, mNorPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ViewGroup.LayoutParams vp = getLayoutParams(); vp.width = ViewGroup.LayoutParams.MATCH_PARENT; vp.height = mHeight; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public void setCurPostion(int pos) { mCurPos = pos; invalidate(); } public void setCount(int count) { mCount = count; } } }

然后提供了一个接口调用:

/** * RecommendView接口 */ public interface IRecommend { void upDate(); void init(); void startAnimation(); void stopAnimation(); }

图片的加载用到了ImageLoad库:

import android.content.Context; import android.graphics.Bitmap; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.papau.show.constant.Constants; import java.io.File; public class ImageLoaderManager { /** * 不带硬盘缓存的options * * @param context * @return */ public static synchronized DisplayImageOptions getCacheOnMemoryOptions(Context context) { DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisk(false) .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) .bitmapConfig(Bitmap.Config.ARGB_8888) // .showImageOnLoading( // context.getResources().getDrawable( // R.drawable.loading_wait)) // .showImageOnFail( // context.getResources().getDrawable( // R.drawable.loading_wait)) .build(); return options; } public static synchronized DisplayImageOptions getCircleOptions(Context context) { DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisk(false) .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) .bitmapConfig(Bitmap.Config.ARGB_8888) // .showImageOnLoading( // context.getResources().getDrawable( // R.drawable.ic_user_head_hint)) // .showImageOnFail( // context.getResources().getDrawable( // R.drawable.ic_user_head_hint)) .build(); return options; } /** * 获取在硬盘中缓存options * * @param context * @return options */ public static synchronized DisplayImageOptions getCacheOnDiskOptions( Context context) { DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisk(true) .imageScaleType(ImageScaleType.EXACTLY) .bitmapConfig(Bitmap.Config.ARGB_8888) // .showImageOnLoading( // context.getResources().getDrawable( // R.drawable.loading_wait)) // .showImageOnFail( // context.getResources().getDrawable( // R.drawable.loading_wait)) .build(); return options; } /** * 获取imageLoader 单例 * * @param context * @return */ public static synchronized ImageLoader getImageLoader(Context context) { ImageLoader imageLoader = ImageLoader.getInstance(); File cacheDir = new File(Constants.sPicCacheLocalPath); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( context).diskCache(new UnlimitedDiskCache(cacheDir)) .threadPoolSize(3) .diskCacheExtraOptions(480, 320, null) .build(); imageLoader.init(config); return imageLoader; } }

使用方法

DisplayMetrics dm = getActivity().getResources().getDisplayMetrics(); RecommendView rv = new RecommendView(getActivity(),dm.widthPixels ,(dm.widthPixels)/2); headViewPager.addView(rv);

以上所述是小编给大家介绍的Android简单实现无限滚动自动滚动的ViewPager,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

时间: 2024-09-28 19:35:29

Android简单实现无限滚动自动滚动的ViewPager的相关文章

Android简单记录和恢复ListView滚动位置的方法_Android

本文实例讲述了Android简单记录和恢复ListView滚动位置的方法.分享给大家供大家参考,具体如下: 有时候我们需要记录当前ListView滚动到的位置,重新加载的时候要回到原位,不罗嗦,给出代码: //列表滚动 private OnScrollListener ScrollLis = new OnScrollListener() { @Override public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3)

Android编程实现TextView垂直自动滚动功能【附demo源码下载】

本文实例讲述了Android编程实现TextView垂直自动滚动功能.分享给大家供大家参考,具体如下: 在做android 应用的开发的时候,横向滚动或者要做出跑马灯的效果很简单,textview本身的属性就支持,只要设置准确就会滚动,开发起来比较简单,但是textview 不支持垂直滚动,那么垂直滚动就需要自己来实现了,很多网友提供的垂直滚 动方案都是千篇一律,使用ScrollView来进行滚动,但是都不完美,做起来有些别扭.有一位网友给出的歌词的滚动思路明确,能从根本上解决问题,因此我实现的

Android仿天天动听歌曲自动滚动view_Android

最近项目中要做一个类似天天动听歌曲自动滚动行数的效果.首先自己想了下Android要滚动的那就是scroller类或者scrollto.scrollby结合了,或者view.layout()方法,或者使用动画.但是要循环滚动,貌似这些到最后一行滚动到第一行都有往回滚的效果,都不是很好的解决方法.怎么会忘记了可以绘制事件万物的的canvas呢.好吧,既然找到了,那就用这个方案吧!但是天天动听歌曲还有一个手动滑动的效果,貌似这篇文章没写.既然这样,那就自己来写下吧!实现之前还是先看下天天动听的效果:

Android简单记录和恢复ListView滚动位置的方法

本文实例讲述了Android简单记录和恢复ListView滚动位置的方法.分享给大家供大家参考,具体如下: 有时候我们需要记录当前ListView滚动到的位置,重新加载的时候要回到原位,不罗嗦,给出代码: //列表滚动 private OnScrollListener ScrollLis = new OnScrollListener() { @Override public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3)

Android仿天天动听歌曲自动滚动view

最近项目中要做一个类似天天动听歌曲自动滚动行数的效果.首先自己想了下Android要滚动的那就是scroller类或者scrollto.scrollby结合了,或者view.layout()方法,或者使用动画.但是要循环滚动,貌似这些到最后一行滚动到第一行都有往回滚的效果,都不是很好的解决方法.怎么会忘记了可以绘制事件万物的的canvas呢.好吧,既然找到了,那就用这个方案吧!但是天天动听歌曲还有一个手动滑动的效果,貌似这篇文章没写.既然这样,那就自己来写下吧!实现之前还是先看下天天动听的效果:

Javascript实现DIV滚动自动滚动到底部的代码_javascript技巧

查询了一下相关的资料,Div没有自动滚动的属性,只能模拟鼠标的滚动来现实想要的效果. 关键的部分部分在这里:div.scrollTop = div.scrollHeight; 下面是具体实现的精简代码: 复制代码 代码如下: <html> <body> <div id="divDetail" style="overFlow-y:scroll; width:250px;height: 200px;"> <table style

Android自动滚动 轮播循环的ViewPager

主要介绍如何实现ViewPager自动播放,循环滚动的效果及使用.顺便解决ViewPager嵌套(ViewPager inside ViewPager)影响触摸滑动及ViewPager滑动速度设置问题. 项目已开源Android Auto Scroll ViewPager@Github,欢迎star和fork. 更多自动滚动轮播的开源项目可见:自动滚动 ViewPager. 示例APK可从这些地址下载:Google Play, 360手机助手, 百度手机助手, 小米应用商店, 豌豆荚 示例代码地

Android 使用ViewPager自动滚动循环轮播效果_Android

对Android 利用ViewPager实现图片可以左右循环滑动效果,感兴趣的朋友可以直接点击查看内容详情. 主要介绍如何实现ViewPager自动播放,循环滚动的效果及使用.顺便解决ViewPager嵌套(ViewPager inside ViewPager)影响触摸滑动及ViewPager滑动速度设置问题. 先给大家展示下效果图,喜欢的朋友可以下载源码: 1.实现 没有通过ScheduledExecutorService或Timer定期执行某个任务实现,而是简单的通过handler发送消息去

Android 使用ViewPager自动滚动循环轮播效果

对Android 利用ViewPager实现图片可以左右循环滑动效果,感兴趣的朋友可以直接点击查看内容详情. 主要介绍如何实现ViewPager自动播放,循环滚动的效果及使用.顺便解决ViewPager嵌套(ViewPager inside ViewPager)影响触摸滑动及ViewPager滑动速度设置问题. 先给大家展示下效果图,喜欢的朋友可以下载源码: 1.实现 没有通过ScheduledExecutorService或Timer定期执行某个任务实现,而是简单的通过handler发送消息去