正常情况下, ViewPager 一页只能显示一项数据, 但是我们常常看到网上,特别是电视机顶盒的首页经常出现中间大图显示两端也都露出一点来,这种效果怎么实现呢?先上一张效果图:
大家第一眼肯定想到了Gallery,这是最早android图库自带的效果,现在基本不用,那有没有其他好的办法呢?我们首先考虑的还是ViewPager+PagerAdapter的实现策略。
后面在网上了搜了一下, 发现要实现上面的效果,我们需要注意两个方面,首先是怎么在两边显示两个小图,第二,怎么实现无限滑动。
1,首先就是用到了View的android:clipChildren属性,.简单来说父View是默认是束缚子View 的显示范围的,所以当我们在父View有 padding , 那么 子View 则在 padding区域是不能显示内容的。当设置android:clipChildren="false"的时候,子View 就可以在父View 的padding内容区域显示内容了。
2,实现无限循环很简单,网上也有很多的解决方案,我这里不考虑性能上的东西,且看下面简单的代码:
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;  }  //这里是viewViewHolder 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添加到另一个组件。

经过上面的解释,我们已经很清楚了,以下是代码的详细实现,数据来源于网上,大家可以自行模拟:

ViewPager类:

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();}@Overridepublic int getCount() {return Integer.MAX_VALUE;}@Overridepublic int getItemPosition(Object object) {return POSITION_NONE;}@Overridepublic 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() {@Overridepublic void onClick(View view) {ToastUtils.showToast("你点击了"+data.href);}});}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic 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.RoundedImageViewandroid: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);}@Overrideprotected void initViews() {contentView = inflate(mContext, R.layout.layout_welfare, this);ButterKnife.bind(this);initViewPager();initTouch();}private void initTouch() {//这里要把父类的touch事件传给子类,不然边上的会滑不动setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return viewPager.dispatchTouchEvent(event);}});viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {position %= welfareList.size();if (position<0){position = welfareList.size()+position;}finefareName.setText(welfareList.get(position).id);}@Overridepublic 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;@Overridepublic 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"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Viewstyle="@style/vertical_bold_line_c8"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"><TextViewstyle="@style/style_c6_s16"android:layout_centerVertical="true"android:text="精品福利" /><TextViewandroid: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.ViewPagerandroid:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="140dp"android:layout_marginLeft="45dp"android:layout_marginRight="45dp"/><TextViewandroid: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.WelfareViewandroid: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,就是上面的代码虽然实现了滑动,却没有真正的实现左右滑动,针对上面的问题,请看下一篇优化篇。

优化方案
写得有点急,欢迎大家留言,有什么不懂得,请进我们的开发群,一定细心讲解: 278792776

ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示相关推荐

  1. 微信小程序手把手教你实现类似Android中ViewPager控件效果

    微信小程序手把手教你实现类似Android中ViewPager控件效果 前言 需求分析 头部TAB 滑动的内容部分 最终版本 尾巴 前言 在做Android开发的时候,ViewPager是开发者使用频 ...

  2. 手把手带你用viewpager实现gallary效果,外加无限循环,自动轮播

    手把手带你用viewpager实现gallary效果,外加无限循环,自动轮播 效果图:图很丑,各位看官且按需更改. 主要功能: ①Gallary样式 ②无限轮播 ③自动轮播和手势操作间冲突解决 提前说 ...

  3. 简单玩转ViewPager+Fragment动画效果,实现京东淘宝物流卡片效果 (附源码)

    物流卡片Demo 新版的京东和淘宝有一个交互感觉不错, 待收货订单会有类似探探那样的卡片效果, 滑动查看下一条物流的信息, 近期UI部门说要做这个效果, 于是我就写了一个Demo, 现在分享出来和大家 ...

  4. 小程序滑动点击切换中间大图两边小图

    小程序 滑动点击 切换中间大图 两边小图 代码太老了已不建议阅读, 简单看下思路即可 整体思路, 使用小程序API的animation动画和组件的canvas中的bindtouchstart.bind ...

  5. 使用Kotlin实现UC头条ViewPager左右滑动效果

    转载请标明出处:一片枫叶的专栏 上一篇文章中我们讲解了一个使用的多行文本显示控件,在实际开发过程中我们时常会遇到这种需求:有两个TextView控件分行显示,当第一个TextView的内容过多一行显示 ...

  6. android双重for循环,Android实现ViewPager无限循环效果(二)

    本文实例为大家分享了Android实现ViewPager无限循环效果的第二种方式,供大家参考,具体内容如下 原理:在Adapter中将getCount设置为无限大 package com.xiaoma ...

  7. ViewPager页面切换效果

    ViewPager页面切换效果 运行效果一:                                                                               ...

  8. jQuery 效果- 隐藏和显示

    jQuery 效果- 隐藏和显示 实例 jQuery hide() 简单的jQuery hide()方法演示. <!DOCTYPE html> <html> <head& ...

  9. jQuery效果-隐藏和显示

    jQuery效果-隐藏和显示 使用jQuery能够轻易地实现各种动画效果,包括隐藏.显示.切换.滑动等 hide()方法和show()方法 通过jQuery,可以使用hide()和show()方法来隐 ...

最新文章

  1. RedHat Enterprise Linux 5.0之LVM逻辑卷管理
  2. 【转】数据库的锁机制
  3. python2 'str' object has no attribute 'decode'
  4. 《CDN 之我见》原理篇——CDN的由来与调度
  5. kubernetes --- Glusterfs
  6. php的cms是什么意思,phpcms是什么
  7. C# Http请求接口数据的两种方式Get and Post
  8. 苹果新Metal API实测:四倍完爆OpenGL ES
  9. mysql for update缺点_有关mysql的for update以及 死锁问题
  10. 【RLchina第五讲】Control as Inference
  11. YAF根据条件拼接SQL语句
  12. TCP/IP协议学习总结
  13. SQL Server 2012 SQLEXPRESS 无法通过IP连接访问问题的解决
  14. C语言中access/_access函数的使用
  15. 在线影音页面的制作方法
  16. java 实现 word 文档的在线编辑以及流转
  17. untiy游戏接入之uc_sdk(九游)
  18. 人脸识别服务器端软件设计(delphi XE10)
  19. 网上购车平台真的靠谱吗?老司机分析给你听
  20. LINUX网络驱动开发

热门文章

  1. 面试题准备(二十六):form 表单
  2. Java毕设项目旅游网站设计(java+VUE+Mybatis+Maven+Mysql)
  3. 计算机硬件系统 ppt 免费,计算机硬件系统课件.ppt
  4. 易软社区诊所门诊病历系统
  5. 咨询入门教程之二--ERP项目咨询顾问的五大能力
  6. 网络性能分析:Y.Rapp近似方法
  7. 快速下载 arXiv论文
  8. 最新调剂流程/小技巧,你想知道的一切都在这里-文都管联院
  9. 华硕t100ha安装linux,华硕T100HA怎么安装win7系统
  10. 计算机体系结构——中央处理器——流水线技术