ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示
private class ImageAdapter extends PagerAdapter{ private ArrayList<String> viewlist; public ImageAdapter(ArrayList<String> viewlist) { this.viewlist = viewlist; } @Override public int getCount() { //设置成最大,使用户看不到边界,大家可以去查询下这个大小 return Integer.MAX_VALUE; } @Override public void destroyItem(ViewGroup container, int position, Object object) { //注:不要在这里调用removeView } @Override public Object instantiateItem(ViewGroup container, int position) { //对ViewPager页号求模取出View列表中要显示的项 position %= viewlist.size(); if (position<0){ position = viewlist.size()+position; } //这里是view 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; } }
上面代码应该注意的几点:
getCount() 方法的返回值:这个值直接关系到ViewPager的“边界”,因此当我们把它设置为Integer.MAX_VALUE之后,用户基本就看不到这个边界了(估计滑到这里的时候电池已经挂了吧o_O)。当然,通常情况下设置为100倍实际内容个数也是可以的,之前看的某个实现就是这么干的。
instantiateItem() 方法position的处理:由于我们设置了count为 Integer.MAX_VALUE,因此这个position的取值范围很大很大,但我们实际要显示的内容肯定没这么多(往往只有几项),所以这里肯定会有求模操作。但是,简单的求模会出现问题:考虑用户向左滑的情形,则position可能会出现负值。所以我们需要对负值再处理一次,使其落在正确的区间内。
instantiateItem() 方法父组件的处理:通常我们会直接addView,但这里如果直接这样写,则会抛出IllegalStateException。假设一共有三个view,则当用户滑到第四个的时候就会触发这个异常,原因是我们试图把一个有父组件的View添加到另一个组件。
经过上面的解释,我们已经很清楚了,以下是代码的详细实现,数据来源于网上,大家可以自行模拟:
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; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @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)); } } }
用到的布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ptr="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <com.yju.app.widght.image.RoundedImageView android:id="@+id/welfare_image" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:scaleType="fitXY" ptr:corner_radius="3dp" android:src="@drawable/welfare_default_icon" /> </LinearLayout>
用到的数据Bean(这个大家根据情况自行模拟,只要是个列表就行)
public class FineFareEntity { public List<PanicBean> panic; public static class PanicBean { public String id; public long endtime; public String pic; public int type; public String href; public String title; public String share; } }
为了方便使用我们都自定义成View,方便以后代码维护:
public class WelfareView extends SimpleLinearLayout { @BindView(R.id.finefare_count) TextView finefareCount; @BindView(R.id.viewPager) ViewPager viewPager; @BindView(R.id.finefare_name) TextView finefareName; @BindView(R.id.welfare_view) LinearLayout welfareView; private WelfareAdapter adapter = null; private List<PanicBean> welfareList = null; public WelfareView(Context context) { super(context); } public WelfareView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void initViews() { contentView = inflate(mContext, R.layout.layout_welfare, this); ButterKnife.bind(this); initViewPager(); initTouch(); } private void initTouch() { //这里要把父类的touch事件传给子类,不然边上的会滑不动 setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return viewPager.dispatchTouchEvent(event); } }); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { position %= welfareList.size(); if (position<0){ position = welfareList.size()+position; } finefareName.setText(welfareList.get(position).id); } @Override public void onPageScrollStateChanged(int state) { } }); } private void initViewPager() { viewPager.setOffscreenPageLimit(3); viewPager.setPageTransformer(true, new ScalePagerTransformer()); //设置Pager之间的间距 viewPager.setPageMargin(UIUtils.dp2px(mContext, 15)); adapter = new WelfareAdapter(mContext); viewPager.setAdapter(adapter); } public void setWelfareData(List<PanicBean> datas) { this.welfareList = datas; welfareView.setVisibility(datas.size()>0?VISIBLE:GONE); finefareCount.setText("共有" + datas.size() + "个福利"); finefareName.setText(welfareList.get(getCurrentDisplayItem()).title); adapter = new WelfareAdapter(mContext); adapter.setDatas(datas); viewPager.setAdapter(adapter); viewPager.setCurrentItem(adapter.getCount() > 0 ? 1 : 0, true); } public int getCurrentDisplayItem() { if (viewPager != null) { return viewPager.getCurrentItem(); } return 0; } }
这里有一个滑动缩放的类:
public class ScalePagerTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; @Override public void transformPage(View view, float position) { if (position >= -1 || position <= 1) { final float height = view.getHeight(); final float width = view.getWidth(); final float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); final float vertMargin = height * (1 - scaleFactor) / 2; final float horzMargin = width * (1 - scaleFactor) / 2; view.setPivotY(0.5f * height); view.setPivotX(0.5f * width); if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } } }
<pre name="code" class="html" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">SimpleLinearLayout 类
public class SimpleLinearLayout extends LinearLayout { protected Context mContext; protected View contentView; protected AtomicBoolean isPreparingData; public SimpleLinearLayout(Context context) { super(context); this.mContext = context; isPreparingData = new AtomicBoolean(false); initViews(); } public SimpleLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; isPreparingData = new AtomicBoolean(false); initViews(); } protected void initViews() { } }
用到的布局(android:clipChildren="false"需要注意):
<span style="color:#333333;"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/welfare_view" android:layout_width="match_parent" android:layout_height="wrap_content" </span><span style="color:#ff0000;">android:clipChildren="false"</span><span style="color:#333333;"> android:layout_marginTop="10dp" android:background="@color/c12" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <View style="@style/vertical_bold_line_c8" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <TextView style="@style/style_c6_s16" android:layout_centerVertical="true" android:text="精品福利" /> <TextView android:id="@+id/finefare_count" style="@style/style_c6_s14" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:drawablePadding="3dp" android:drawableRight="@drawable/arrow" android:text="共有n个福利" /> </RelativeLayout> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="140dp" android:layout_marginLeft="45dp" android:layout_marginRight="45dp" /> <TextView android:id="@+id/finefare_name" style="@style/style_c8_s16" android:layout_gravity="center" android:layout_marginBottom="15dp" android:layout_marginTop="15dp" android:text="" /> </LinearLayout> </span>
最后就是在我们的主代码中写个歌测试了,
private void initWelfare() { String welfare = FileUtils.readAssert(getActivity(), "welfare.txt"); FineFareEntity entity=JsonUtils.parseJson(welfare,FineFareEntity.class); if (entity!=null){ welfareView.setWelfareData(entity.panic); } }
涉及到的布局:
<com.yju.app.shihui.welfare.view.WelfareView android:id="@+id/welfare_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="160dp" />
这里的FileUtils.readAssert 代码:
public static String readAssert(Context context, String fileName){ String resultString=""; try { InputStream inputStream=context.getResources().getAssets().open(fileName); byte[] buffer=new byte[inputStream.available()]; inputStream.read(buffer); resultString=new String(buffer,"utf-8"); } catch (Exception e) { e.printStackTrace(); } return resultString; }
最后为了方便大家的模拟,我把数据给大家,有点多,大家自己放到assert目录下,
{ panic: [ { id: "2412", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M04/E3/67/CgvUBVe9vyOAV47CAACXZZs5GrU558_o.jpg", type: 1, href: "http://evt.ymatou.com/n770", title: "今日限时抢", share: "" }, { id: "2417", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M09/E4/37/CgvUA1e91VmAMYrwAAC5qcblOUg650_o.jpg", type: 1, href: "http://evt.ymatou.com/n781", title: "今日限时抢", share: "" }, { id: "2413", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M05/E3/D4/CgvUA1e9v2SAVf3qAAB9GcBIWYA268_o.jpg", type: 1, href: "http://evt.ymatou.com/n771", title: "今日限时抢", share: "" }, { id: "2414", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M05/E3/69/CgvUBVe9v4aAMaFRAABWy73vn2g252_o.jpg", type: 1, href: "http://evt.ymatou.com/n772", title: "今日限时抢", share: "" }, { id: "2415", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M06/E3/02/CgvUBFe9v6WAP85NAAC6EK5e5Vg469_o.jpg", type: 1, href: "http://evt.ymatou.com/n773", title: "今日限时抢", share: "" }, { id: "2416", endtime: 1472097600000, pic: "http://pc1.img.ymatou.com/G02/M06/E3/02/CgvUBFe9v8CAHyXVAACELcKFT_M328_o.jpg", type: 1, href: "http://evt.ymatou.com/n775", title: "今日限时抢", share: "" } ] }
其实针对上面的代码,有个bug,就是上面的代码虽然实现了滑动,却没有真正的实现左右滑动,针对上面的问题,请看下一篇优化篇。
ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示的更多相关文章
- ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)
上一张效果图: 之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构.ViewPager实现Galler效果,但是当 ...
- 【笔记】WPF实现ViewPager引导界面效果及问题汇总
最近在开发项目的首次使用引导界面时,遇到了问题,引导界面类似于安卓手机ViewPager那样的效果,希望通过左右滑动手指来实现切换不同页面,其间伴随动画. 实现思路: 1.界面布局:新建一个UserC ...
- 基于jQuery左侧小图滚动右侧大图显示代码
今天给大家分享一款 jQuery左侧小图滚动右侧大图显示代码是一款基于jQuery实现的左侧滚动图片点击大图查看效果代码.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari. ...
- jQuery 效果 —— 隐藏和显示
jQuery 效果 -- 隐藏和显示 1.隐藏和显示 (1)在jQuery中我们可以使用hide()和show()分别隐藏和显示HTML元素: //隐藏元素 $("button") ...
- 精致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 记得关于照片墙的文章我已经写过好几篇了,有最基本的照片墙,有瀑布流模 ...
- 【安卓高级】ViewPager视差动画效果
在安卓开发中,是否遇见过一些很酷的视差动画效果,当ViewPager滑动下一页的时候,页面内的各种元素也能跟随滑动做位移效果,整体看起来非常有活力. 关键的PageTransformer PageTr ...
随机推荐
- oracle拆分一个连续的字符串
create or replace procedure pc( sss out varchar2)isstr varchar2(20):='ph,p,cod,do,cu';en integer:=i ...
- dubbo服务的发布和调用
Dubbo是分布式服务架构,是一个优秀的开源服务型框架,使得应用可以通过高性能的rpc实现服务的输入和输出功能.其实dubbo就是资源调度和治理中心的管理工具. 发布dubbo服务:在提供服务的应用中 ...
- 剑指架构师系列-Logstash分布式系统的日志监控
Logstash主要做由三部署组成: Collect:数据输入 Enrich:数据加工,如过滤,改写等 Transport:数据输出 下面来安装一下: wget https://download.el ...
- Nodejs 模块查找机制还不错(从当前目录开始逐级向上查找node_modules)
比如 m.js是能够调用a.js的, 这样子目录就可以避免重复安装node_modules. 够用了.
- Gradle 1.12用户指南翻译——第四十八章. Wrapper 插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- 新浪微博Oauth2.0授权认证及SDK、API的使用(Android)
---------------------------------------------------------------------------------------------- [版权申明 ...
- HBase的环境配置及其应用
-------------------------------------------------------------------------------------- [版权申明:本文系作者原创 ...
- DoesNotExist at /admin/
DoesNotExist at /admin/ User has no account. Request Method: GET Request URL: http://127.0.0.1:8000/ ...
- CentOS6.7下安装MySQL
第一步:到MySQL官网上下载linux版本的MySQL rpm 安装包. 第二步: 将该压塑包解压后,有如下文件: 第三步:安装文件,我们需要安装的文件有 MySQL-server-5.6.26-1 ...
- ssh用法及命令
http://blog.csdn.net/pipisorry/article/details/52269785 什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录.如果一个用户从本 ...