ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)
上一张效果图:
之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构。ViewPager实现Galler效果,但是当时时间比较急,写的比较仓促,上一篇实现了简单的效果,但是对于初始的时候左边滑动是有问题的,这是因为我们在自己的Adapter的时候对于getCount,我们想通过Integer.MAX_VALUE来实现无限循环,简单的说这个是向右(无限大)吧,所以也就只是实现了向右的循环,对于像左的还是不行的。
那么怎么解决呢?
首先我们对Adapter还是需要按以前的写法,其实Adapter适配器就是帮我们做界面的,其他的逻辑最好不要加,我之前的想法是用过
viewPager.addOnPageChangeListener来实现,通过判断是否滑到最左边或者最右边来实现循环滑到。
int realPosition = mAdapter.toRealPosition(position); if (mPreviousPosition != realPosition) { mPreviousPosition = realPosition; if (mOuterPageChangeListener != null) { mOuterPageChangeListener.onPageSelected(realPosition); } }这里我封装了一个类,只要将你的ViewPager改为我封装好的ViewPager就行
LoopViewPager
public class LoopViewPager extends ViewPager { private static final boolean DEFAULT_BOUNDARY_CASHING = false; private OnPageChangeListener mOuterPageChangeListener; private LoopPagerAdapterWrapper mAdapter; private boolean mBoundaryCaching = DEFAULT_BOUNDARY_CASHING; public static int toRealPosition( int position, int count ){ position = position-1; if( position < 0 ){ position += count; }else{ position = position%count; } return position; } public void setBoundaryCaching(boolean flag) { mBoundaryCaching = flag; if (mAdapter != null) { mAdapter.setBoundaryCaching(flag); } } @Override public void setAdapter(PagerAdapter adapter) { mAdapter = new LoopPagerAdapterWrapper(adapter); mAdapter.setBoundaryCaching(mBoundaryCaching); super.setAdapter(mAdapter); setCurrentItem(0, false); } @Override public PagerAdapter getAdapter() { return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter; } @Override public int getCurrentItem() { return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0; } public void setCurrentItem(int item, boolean smoothScroll) { int realItem = mAdapter.toInnerPosition(item); super.setCurrentItem(realItem, smoothScroll); } @Override public void setCurrentItem(int item) { if (getCurrentItem() != item) { setCurrentItem(item, true); } } @Override public void setOnPageChangeListener(OnPageChangeListener listener) { mOuterPageChangeListener = listener; }; public LoopViewPager(Context context) { super(context); init(); } public LoopViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { super.setOnPageChangeListener(onPageChangeListener); } private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() { private float mPreviousOffset = -1; private float mPreviousPosition = -1; @Override public void onPageSelected(int position) { int realPosition = mAdapter.toRealPosition(position); if (mPreviousPosition != realPosition) { mPreviousPosition = realPosition; if (mOuterPageChangeListener != null) { mOuterPageChangeListener.onPageSelected(realPosition); } } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int realPosition = position; if (mAdapter != null) { realPosition = mAdapter.toRealPosition(position); if (positionOffset == 0 && mPreviousOffset == 0 && (position == 0 || position == mAdapter.getCount() - 1)) { setCurrentItem(realPosition, false); } } mPreviousOffset = positionOffset; if (mOuterPageChangeListener != null) { if (realPosition != mAdapter.getRealCount() - 1) { mOuterPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels); } else { if (positionOffset > .5) { mOuterPageChangeListener.onPageScrolled(0, 0, 0); } else { mOuterPageChangeListener.onPageScrolled(realPosition, 0, 0); } } } } @Override public void onPageScrollStateChanged(int state) { if (mAdapter != null) { int position = LoopViewPager.super.getCurrentItem(); int realPosition = mAdapter.toRealPosition(position); if (state == ViewPager.SCROLL_STATE_IDLE && (position == 0 || position == mAdapter.getCount() - 1)) { setCurrentItem(realPosition, false); } } if (mOuterPageChangeListener != null) { mOuterPageChangeListener.onPageScrollStateChanged(state); } } }; }LoopPagerAdapterWrapperpublic class LoopPagerAdapterWrapper extends PagerAdapter { private PagerAdapter mAdapter; private SparseArray<ToDestroy> mToDestroy = new SparseArray<ToDestroy>(); private boolean mBoundaryCaching; void setBoundaryCaching(boolean flag) { mBoundaryCaching = flag; } LoopPagerAdapterWrapper(PagerAdapter adapter) { this.mAdapter = adapter; } @Override public void notifyDataSetChanged() { mToDestroy = new SparseArray<ToDestroy>(); super.notifyDataSetChanged(); } int toRealPosition(int position) { int realCount = getRealCount(); if (realCount == 0) return 0; int realPosition = (position-1) % realCount; if (realPosition < 0) realPosition += realCount; return realPosition; } public int toInnerPosition(int realPosition) { int position = (realPosition + 1); return position; } private int getRealFirstPosition() { return 1; } private int getRealLastPosition() { return getRealFirstPosition() + getRealCount() - 1; } @Override public int getCount() { return mAdapter.getCount() + 2; } public int getRealCount() { return mAdapter.getCount(); } public PagerAdapter getRealAdapter() { return mAdapter; } @Override public Object instantiateItem(ViewGroup container, int position) { int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter) ? position : toRealPosition(position); if (mBoundaryCaching) { ToDestroy toDestroy = mToDestroy.get(position); if (toDestroy != null) { mToDestroy.remove(position); return toDestroy.object; } } return mAdapter.instantiateItem(container, realPosition); } @Override public void destroyItem(ViewGroup container, int position, Object object) { int realFirst = getRealFirstPosition(); int realLast = getRealLastPosition(); int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter) ? position : toRealPosition(position); if (mBoundaryCaching && (position == realFirst || position == realLast)) { mToDestroy.put(position, new ToDestroy(container, realPosition, object)); } else { mAdapter.destroyItem(container, realPosition, object); } } @Override public void finishUpdate(ViewGroup container) { mAdapter.finishUpdate(container); } @Override public boolean isViewFromObject(View view, Object object) { return mAdapter.isViewFromObject(view, object); } @Override public void restoreState(Parcelable bundle, ClassLoader classLoader) { mAdapter.restoreState(bundle, classLoader); } @Override public Parcelable saveState() { return mAdapter.saveState(); } @Override public void startUpdate(ViewGroup container) { mAdapter.startUpdate(container); } @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { mAdapter.setPrimaryItem(container, position, object); } static class ToDestroy { ViewGroup container; int position; Object object; public ToDestroy(ViewGroup container, int position, Object object) { this.container = container; this.position = position; this.object = object; } } }这里需要注意对于上一篇的WelfareAdapter ,我们就按常规写法就行。
public class WelfareAdapter extends PagerAdapter { private Context mContext; private List<PanicBean> dataList = new ArrayList<>(); public WelfareAdapter(Context mContext) { this.mContext = mContext; } public void setDatas(List<PanicBean> list) { if (list.size() <= 0) { dataList.clear(); notifyDataSetChanged(); return; } dataList.clear(); dataList.addAll(list); notifyDataSetChanged(); } @Override public int getCount() { return /*Integer.MAX_VALUE*/dataList.size(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public void destroyItem(View container, int position, Object object) { } @Override public Object instantiateItem(ViewGroup container, int position) { // position %= dataList.size(); // if (position<0){ // position = dataList.size()+position; // } PanicBean data = dataList.get(position); ViewHolder viewHolder = null; View view = LayoutInflater.from(mContext).inflate( R.layout.item_finefare_layout, null); if (viewHolder == null) { viewHolder = new ViewHolder(view); } bindView(viewHolder, data); container.addView(view, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); return view; } private void bindView(ViewHolder viewholder, final PanicBean data) { Glide.with(mContext).load(data.pic).into(viewholder.welfareImage); viewholder.welfareImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ToastUtils.showToast("你点击了"+data.href); } }); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } class ViewHolder { @BindView(R.id.welfare_image) RoundedImageView welfareImage; ViewHolder(View view) { ButterKnife.bind(this, view); view.setTag(this); } public void reset() { welfareImage.setBackground(mContext.getResources().getDrawable(R.drawable.welfare_default_icon)); } } }
ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)的更多相关文章
- ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示
正常情况下, ViewPager 一页只能显示一项数据, 但是我们常常看到网上,特别是电视机顶盒的首页经常出现中间大图显示两端也都露出一点来,这种效果怎么实现呢?先上一张效果图: 大家第一眼肯定想到了 ...
- 【笔记】WPF实现ViewPager引导界面效果及问题汇总
最近在开发项目的首次使用引导界面时,遇到了问题,引导界面类似于安卓手机ViewPager那样的效果,希望通过左右滑动手指来实现切换不同页面,其间伴随动画. 实现思路: 1.界面布局:新建一个UserC ...
- 基于jQuery左侧小图滚动右侧大图显示代码
今天给大家分享一款 jQuery左侧小图滚动右侧大图显示代码是一款基于jQuery实现的左侧滚动图片点击大图查看效果代码.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari. ...
- jQuery 效果 —— 隐藏和显示
jQuery 效果 -- 隐藏和显示 1.隐藏和显示 (1)在jQuery中我们可以使用hide()和show()分别隐藏和显示HTML元素: //隐藏元素 $("button") ...
- windows7文件夹怎样默认图片大图显示?
先打开一个含有图片的文件夹,在文件夹空白处右键选择属性,打开自定义选项卡. 确定自定义选项卡 显示的是:“优化此文件夹:图片”. 然后,选择:组织--文件夹和搜索选项--查看--文件夹视图,应用到文件 ...
- 精致3D图片切换效果,最适合企业产品展示
这是一个精致的立体图片切换效果,特别适合企业产品展示,可立即用于实际项目中.支持导航和自动播放功能, 基于 CSS3 实现,推荐使用最新的 Chrome,Firefox 和 Safari 浏览器浏览效 ...
- TexturePacker大图还原成小图工具带源码
TexturePacker是一个把好多小图打成大图的软件,生成的是大图以及小图在大图位置的.plist描述文件,但是不支持把大图还原成小图.网上偷的图一般都是大图和plist,想得到小图比较麻烦,于是 ...
- Python - 工具:将大图切片成小图,将小图组合成大图
训练keras时遇到了一个问题,就是内存不足,将 .fit 改成 .fit_generator以后还是放不下一张图(我的图片是8192×8192的大图==64M).于是解决方法是将大图切成小图,把小图 ...
- Android照片墙加强版,使用ViewPager实现画廊效果
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/12646775 记得关于照片墙的文章我已经写过好几篇了,有最基本的照片墙,有瀑布流模 ...
随机推荐
- vue移动端组件库vux使用小记
1.首先安装vux:npm install vux 2.安装vux-loader:npm install vux-loader 3.确认是否已安装less-loader:npm install ...
- js强大的日期格式化函数,不仅可以格式化日期,还可以查询星期,一年中第几天等
js强大的日期格式化,timestamp支持10位或13位的时间戳,或是时间字符串,同时支持android ios的处理,不只是日期的格式化还有其它方法,比如获 获取某月有多少天 .获取某个日期在这一 ...
- COCO 数据集的使用
Windows 10 编译 Pycocotools 踩坑记 COCO数据库简介 微软发布的COCO数据库, 除了图片以外还提供物体检测, 分割(segmentation)和对图像的语义文本描述信息. ...
- CSS实现元素居中原理解析
在 CSS 中要设置元素水平垂直居中是一个非常常见的需求了.但就是这样一个从理论上来看似乎实现起来极其简单的,在实践中,它往往难住了很多人. 让元素水平居中相对比较简单:如果它是一个行内元素,就对它的 ...
- HTTP与TCP的关系
一直比较想写TCP与HTTP之间的关系,HTTP报文是如何通过tcp发送的,HTTP报文形式内容如何. HTTP请求包含请求行,请求头,请求体 HTTP响应包含响应头,响应头,响应体 下面我准备通过J ...
- ACM Misha and Changing Handles
Misha hacked the Codeforces site. Then he decided to let all the users change their handles. A user ...
- ACM Find them, Catch them
The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TW ...
- PHP MySQL Where 子句
WHERE 子句 WHERE 子句用于提取满足指定标准的的记录. 语法 SELECT column_name(s) FROM table_name WHERE column_name operator ...
- 20160221.CCPP体系详解(0031天)
程序片段(01):01.结构体静态数组.c+02.结构体动态数组.c 内容概要:结构体数组 ///01.结构体静态数组.c #include <stdio.h> #include < ...
- Weblogic 12c 集群环境搭建
本文是在windows7操作系统下配置的,jdk版本1.7 ,weblogic版本12.1.3.0.0. 搭建集群前的规划 其中AdminServer是总控制端,server1.server2.ser ...