[Android]使用ViewPager实现图片滑动展示
在淘宝等电商的APP首页经常能看到大幅的广告位,通常有多幅经常更新的图片用于展示促销信息,如下图所示:

通常会自动滚动,也可以根据手势滑动。我没有研究过人家的APP是通过什么实现的,可能有第三方已经封装好的控件可以直接使用,也可能通过webview来实现,毕竟在网页上也有很多类似的内容。如果有高手经验丰富不妨指点一二。不管别人怎样,今天我准备自己动手做一个,其实也不是特别复杂的。
我主要使用的实现方法是Android自带的ViewPager控件,这个控件主要用于实现屏幕水平切换,有自带的动画效果。Android官网上有使用教程:http://developer.android.com/training/animation/screen-slide.html,当然下文会有相一致的说明。
然后就开始动手实现这个图片滑动效果吧。
1. 首先解释一下ViewPager的使用过程,通常来说ViewPager可以和Fragment结合起来用,每次ViewPager滑动,也就是展示一个新的Fragment。Fragment里面就是我们需要展现的内容。而这滑动的动画就交给ViewPager来实现。所以第一步我们需要设置好Fragment的内容,新建一个布局文件,这里只需要展示一张图即可,当然可以根据自己的需要进行改变:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <ImageView
android:id="@+id/iv_main_pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/main_image"
android:scaleType="fitXY" /> </RelativeLayout>
2. 然后建立Fragment类。
import android.support.v4.app.Fragment;
...... public class PictureSlideFragment extends Fragment { @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_picture_slide, container, false); return v;
} }
3. 在Activity布局文件的合适位置加入ViewPager控件。
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
4. 在Activity中得到这个ViewPager并且为其设置Adapter:
private ViewPager mPager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new PictureSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
5. 这个Adapter继承自FragmentStatePagerAdapter,其中getCount()返回的值是一共需要显示的内容数,是个常数:
private class PictureSlidePagerAdapter extends FragmentStatePagerAdapter {
public PictureSlidePagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return new PictureSlideFragment();
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return NUM_PIC;
}
}
6. 到目前为止所有的内容都和官方的教程一致。如果你在Fragment中的那个ImageView通过android:src属性设置图片,会实现数张静态图片滑动的效果。这离我们的目标还有一些区别:
(1)图片需要能够动态改变,而不是固定的内容;
(2)每张图片需要有点击的响应;
(3)一般情况下需要实现循环滚动,即滑到最后一张图时继续滑动会回到第一张图;
(4)图片要能够自动滚动;
(5)图片下方需要有显示第几张图的指示(小圆点)。
7. 接下来我们朝着目标继续努力。首先是图片的变化。观察上述Adapter的实现方法,可以发现getItem()方法每次返回的都是一个Fragment的实例,需要显示多少个Fragment这个方法就会执行多少遍。但我们发现每次创建新的Fragment都没有区别,直接new一个了事,因此我们需要改写这个创建新Fragment实例的方法,以实现每次新建的Fragment实例都不一样。在我们的Fragment类中补充如下内容:
private int mIndex;
public static PictureSlideFragment newInstance(int index) {
PictureSlideFragment f = new PictureSlideFragment();
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mIndex = getArguments() != null ? getArguments().getInt("index") : 1;
}
这个叫做newInstance的方法主要功能也是创建一个Fragment实例,和直接new的区别是传递进来一个index参数,这个参数在onCreate()方法中被获得。然后我们将Adapter的getItem()改写为如下:
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return PictureSlideFragment.newInstance(arg0);
}
每次getItem都将Item的序号传递到新建的Fragment,然后再Fragment中根据需要设定不同的内容。真正实现的时候,可以在Fragment中加入从网络获取图片的操作。
8. 图片的点击响应。这个比较简单,在Fragment中获得ImageView控件,然后设置onClick监听器即可。就不给出代码了。
9. 图片的循环滚动。一般的ViewPager不能实现内容的循环滚动,即第一张向左滑或者最后一张向右滑都会到顶,显示到顶的效果。如果要从ViewPager自身入手加入这功能需要对这个控件进行改写,比较麻烦,这里我从stackoverflow上找到了一种比较聪明的办法。
要实现几张图的循环滚动,其实只需要满足视觉效果就可以了。比如有三张图A,B,C,要实现A->B->C->A->B......以及C->B->A->C->B...这样的循环,实际上可以这样实现:
提供5张图,分别是C' A B C A',其中C'和C,A'和A完全相同,当滑到C'时,自动切换到C,当滑到A'时,自动切换到A,并且这个切换过程没有动画,于是,使用者体验出来的感觉就是A B C三张图在循环滚动了。
于是我们为ViewPager添加setOnPageChangeListener方法:
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int state) {
// 当到第一张时切换到倒数第二张,当到最后一张时切换到第二张
if (state == ViewPager.SCROLL_STATE_IDLE) {
int curr = mPager.getCurrentItem();
int lastReal = mPager.getAdapter().getCount() - 2;
if (curr == 0) {
mPager.setCurrentItem(lastReal, false);
} else if (curr > lastReal) {
mPager.setCurrentItem(1, false);
}
}
}
});
覆写的onPageScrollStateChanged方法在滑动内容改变时调用,在其中实现C'和C,A'和A的切换。
10. 图片的自动滚动,这里我使用了timer启动线程来实现,定时器线程每隔5秒发送消息,UI线程捕获消息并调用ViewPager.setCurrentItem(currentItem+1, true)方法,滚动到下一张图片。代码就不赘述了。这里有个体验细节,就是当使用者用手指滑动时,定时器需要取消,防止自动滑动和手指滑动发生冲突。这个我在Fragment的ImageView的onTouchListener中实现:
mMainImage.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
((MainActivity)getActivity()).getTimer().cancel();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
((MainActivity)getActivity()).startSwitchImage();
}
return false;
}
});
11. 图片序号的指示,也就是图片下方的几个小圆点,这个实现比较简单,首先在Activity的布局文件中添加几个图片,因为这几个小圆点本身不能随ViewPager移动,因此不能放在Fragment布局中。切换内容也就是切换显示不同颜色小圆点的位置,这个方法同样可以在onPageScrollStateChanged方法中调用。注意一些细节,因为之前为了实现循环滚动而多用了两个Fragment,而显示的小圆点数量不能增加,因此需要调整好对应的序号。代码也不再赘述了。
最终的效果如下图所示,美食有木有。总结一下,整个过程并不复杂,就是一些细节需要仔细推敲。虽然做法可能有非主流的地方,但实现的效果跟别人的几乎完全一致,这样就行啦~
另外,这样的实现方法也不是完全没有值得改进的地方,比如图片自动滚动的延时还不能自定义。ViewPager没有现成的方法用来自改变自动滚动延时,如果需要自定义,就要自己改写这个控件啦,有兴趣的可以研究一下~

[Android]使用ViewPager实现图片滑动展示的更多相关文章
- 循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示
在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情 ...
- 114、Android禁止ViewPager的左右滑动
有时候在开发中会遇到一些“诡异”的要求,比如在ViewPager中嵌入ListView,或者再嵌入一个ViewPager,那么在滑动的时候就会造成被嵌入的XXView不能滑动了,那么现在就把最外层的V ...
- Android listview viewpager解决冲突 滑动
Android listview viewpager滑动 跳动 冲突解决 ListView中嵌套ViewPage有或者滑动手势冲突解决 在listview 上使用 addHeaderView 在第 ...
- Android禁止ViewPager的左右滑动
转载请注明出处:http://blog.csdn.net/allen315410/article/details/40744287 有时候在开发中会遇到一些"诡异"的要求,比方在V ...
- 011 Android TabLayout+ViewPager实现顶部滑动效果(多个页面)
1.TabLayout介绍 TabLayout提供了一个水平的布局用来展示Tabs,很多应用都有这样的设计,典型的有网易新闻,简书,知乎等.TabLayout就可以很好的完成这一职责,首先TabLay ...
- 一个不错的图片滑动展示插件 anythingslider
一个不错的图片http://css-tricks.com/anythingslider-jquery-plugin/ DEMO演示: http://css-tricks.github.io/Anyth ...
- 《JavaScript 实战》:实现图片幻滑动展示效果
滑动展示效果主要用在图片或信息的滑动展示,也可以设置一下做成简单的口风琴(Accordion)效果.这个其实就是以前写的图片滑动展示效果的改进版,那是我第一篇比较受关注的文章,是时候整理一下了. 有如 ...
- Android使用ViewFlipper实现左右滑动效果面
在我的博客中,上次是使用ViewPager实现左右滑动的效果的,请看文章:Android使用ViewPager实现左右滑动效果. 这次我来使用ViewFlipper实现这种效果,好了,先看看效果吧: ...
- Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能
在实际的开发中,我们市场会遇到这样的情况:点击某图片,浏览某列表(某列表详情)中的所有图片数据,当然,这些图片是可以放大和缩小的,比如我们看下百度贴吧的浏览大图的效果: 链接 这种功能,在一些app ...
随机推荐
- Javascript和jquery事件--鼠标移动事件mousemove
mousemove,一个监听元素上鼠标移动的事件,如果鼠标在元素上移动,大概每16毫秒触发一次.我觉得挺有趣的一个元素,不过有替代还是不太推荐,从这个事件的触发频率就可以看出它会拖慢响应速度,消耗资源 ...
- (转)linux的一个find命令配合rm删除某天前的文件
转自:http://www.cnblogs.com/mingforyou/p/3930624.html 语句写法:find 对应目录 -mtime +天数 -name "文件名" ...
- 《JavaScript高级程序设计》笔记——第一章到第三章
2019年,新年伊始,我打算好好重读一下<JavaScript高级程序设计>这本前端必备经典书.每天半小时. 以下内容摘自<JavaScript高级程序设计> 2019-2-1 ...
- iTestin云测工具
软件概述 iTestin是免费服务移动App开发者的真机自动化云测试客户端工具.基于真实的智能终端设备录制一个测试脚本然后运行,并输出运行结果.覆盖Android和iOS两大设备平台,支持Pad/Ph ...
- proxool数据库连接池用法
今天给大家介绍一种新的数据连接池实现方式--proxool数据库连接池,这是一个健壮.易用的连接池.以下通过一个Demo说明一下怎样使用: 项目结构例如以下: DBLink.java文件里的代码: p ...
- 2.CCGridAction(3D效果),3D反转特效,凸透镜特效,液体特效,3D翻页特效,水波纹特效,3D晃动的特效,扭曲旋转特效,波动特效,3D波动特效
1 类图组织 2 实例 CCSprite * spr = CCSprite::create("HelloWorld.png"); spr->setPosition(cc ...
- gdb查看线程堆栈信息
查看堆栈:gdb -quiet -batch -ex='thread apply all bt' -p pid查看运行位置:gdb -quiet -batch -ex='thread apply al ...
- URL validation failed. The error could have been caused through the use of the browser's navigation
URL validation failed. The error could have been caused through the use of the browser's navigation ...
- [Recompose] Add Local State with Redux-like Reducers using Recompose
Learn how to use the 'withReducer' higher order component using the alternative reducer form. If you ...
- 【翻译自mos文章】Clusterware间歇性的hang,命令报CRS-184而且Network Socket Files in /tmp/.oracle or /var/tmp/.oracle被删
来源于: Clusterware Intermittently Hangs And Commands Fail With CRS-184 as Network Socker Files in /tmp ...