在淘宝等电商的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实现图片滑动展示的更多相关文章

  1. 循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

    在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情 ...

  2. 114、Android禁止ViewPager的左右滑动

    有时候在开发中会遇到一些“诡异”的要求,比如在ViewPager中嵌入ListView,或者再嵌入一个ViewPager,那么在滑动的时候就会造成被嵌入的XXView不能滑动了,那么现在就把最外层的V ...

  3. Android listview viewpager解决冲突 滑动

    Android listview viewpager滑动 跳动 冲突解决 ListView中嵌套ViewPage有或者滑动手势冲突解决   在listview 上使用 addHeaderView 在第 ...

  4. Android禁止ViewPager的左右滑动

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40744287 有时候在开发中会遇到一些"诡异"的要求,比方在V ...

  5. 011 Android TabLayout+ViewPager实现顶部滑动效果(多个页面)

    1.TabLayout介绍 TabLayout提供了一个水平的布局用来展示Tabs,很多应用都有这样的设计,典型的有网易新闻,简书,知乎等.TabLayout就可以很好的完成这一职责,首先TabLay ...

  6. 一个不错的图片滑动展示插件 anythingslider

    一个不错的图片http://css-tricks.com/anythingslider-jquery-plugin/ DEMO演示: http://css-tricks.github.io/Anyth ...

  7. 《JavaScript 实战》:实现图片幻滑动展示效果

    滑动展示效果主要用在图片或信息的滑动展示,也可以设置一下做成简单的口风琴(Accordion)效果.这个其实就是以前写的图片滑动展示效果的改进版,那是我第一篇比较受关注的文章,是时候整理一下了. 有如 ...

  8. Android使用ViewFlipper实现左右滑动效果面

    在我的博客中,上次是使用ViewPager实现左右滑动的效果的,请看文章:Android使用ViewPager实现左右滑动效果. 这次我来使用ViewFlipper实现这种效果,好了,先看看效果吧: ...

  9. Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能

    在实际的开发中,我们市场会遇到这样的情况:点击某图片,浏览某列表(某列表详情)中的所有图片数据,当然,这些图片是可以放大和缩小的,比如我们看下百度贴吧的浏览大图的效果:  链接 这种功能,在一些app ...

随机推荐

  1. [Angular] Show a loading indicator in Angular using *ngIf/else, the as keyword and the async pipe

    The network may be unreliable and loading data may take time. Thus it is important to give the user ...

  2. 【SPOJ QTREE】树链剖分模板

    用线段树求解,这里注意因为求的是路径最大值,注意一下细节. #include<cstdio> #include<cstring> #include<algorithm&g ...

  3. Web前端--黑客技术揭秘(菜鸟知识)

    一,Web安全的关键点 1.同源策略是众多安全策略的一个,是Web层面上的策略.很重要. 2.同源策略规定:不同域的client脚本在没明白授权的情况下.不能读写对方的资源. 3.同域要求两个网站同协 ...

  4. stm32的DMA传输一半中断

    这里本想做一个录音程序 硬件很简单: MIC(麦克风)放大滤波电路---->stm32的ADC----->DMA通道----->一个数组缓存------->通过FATFS的  ...

  5. 数据类型总结——Boolean类型(布尔类型)

    相关文章 简书原文:https://www.jianshu.com/p/e5c75d4be636 数据类型总结——概述:https://www.cnblogs.com/shcrk/p/9266015. ...

  6. python 升级pip

    废话少说,直接上图,希望谅解我的懒惰!:)

  7. C语言数据类型取值范围解析

    版权声明:本文为博主原创文章,未经博主允许不得转载.   为什么int类型的取值范围会是-2^31 ~ 2^31-1  ,为什么要减一呢? 计算机里规定,8位二进制为一个字节,拿byte来说,一个BY ...

  8. Springmvc+Shiro实战

    原文链接:http://blog.csdn.net/qq_37936542/article/details/79010449 springmvc+shiro实现系统粗细粒度的权限管理步骤: 1:表格设 ...

  9. [CSS] Re-order the appearance of grid items using the order property

    As with flex items, we can set an order value on grid items. Let’s see how this affects the DOM and ...

  10. [Grid Layout] Use auto-fill and auto-fit if the number of repeated grid tracks is not to be def

    What about the situation in which we aren’t specifying the number of columns or rows to be repeated? ...