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 ...
随机推荐
- Windows无法安装到这个磁盘
今天手动装系统的时候出现以下这样的错误, 请看图: 进入BIOS F9 Setup Defaults ,初始化恢复 1.在进行windows安装分区时, 磁盘分区界面无法继续进行,出现" ...
- Oracle中rownum原理介绍
rownum原理如下:1.执行查询操作2.将第一行的row num置为13.将得到的行的row num与条件相比较,如果不匹配,则抛弃行,如果匹配,则返回行4.oracle获取下一行,然后将rownu ...
- ACM Let the Balloon Rise
Contest time again! How excited it is to see balloons floating around. But to tell you a secret, the ...
- 20160208.CCPP体系详解(0018天)
程序片段(01):main.c 内容概要:PointWithOutInit #include <stdio.h> #include <stdlib.h> //01.野指针详解: ...
- JavaScript DOM详解
欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/52727448 本文出自:[余志强的博客] 一.DOM概述 D: Do ...
- ROS机器人程序设计(原书第2版)补充资料 (壹) 第一章 ROS系统入门
ROS机器人程序设计(原书第2版)补充资料 (壹) 第一章 ROS系统入门 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 第一章主要包括R ...
- 数组中的数分为两组,让给出一个算法,使得两个组的和的差的绝对值最小,数组中的数的取值范围是0<x<100,元素个数也是大于0, 小于100 。
比如a[]={2,4,5,6,7},得出的两组数{2,4,6}和{5,7},abs(sum(a1)-sum(a2))=0: 比如{2,5,6,10},abs(sum(2,10)-sum(5,6))=1 ...
- SpringMVC常用配置
关于Spring.SpringMVC我们前面几篇博客都介绍了很多,但是还不够,这些框架中涉及到的注解.配置非常多,那么我们今天再来介绍一个SpringMVC的基本配置,灵活的使用这些配置,可以让我们在 ...
- javap反编译命令详解&Eclipse中配置javap命令
javap命令所有参数如下图所示: javap 命令用于解析类文件.其输出取决于所用的选项.若没有使用选项,javap 将输出传递给它的类的 public 域及方法.javap 将其输出到标准输出设备 ...
- Android App之间通过Intent交互
Android 最重要的功能之一是应用能够基于它要执行的"操作"向另一个应用发送用户. 例如,如果您的应用有您要在地图上显示的公司地址,您无需在显示地图的应用中构建 Activit ...