关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户"友好性",下面来看几个示例图:

  

再来看下我仿写的效果:

关于广告轮播Banner这个东西,GitHub上面应该有现成的开源组件,不过我没去找过,觉得实现起来不会太难,就自己去仿写了,下面我说下实现的思路:

1、首先看到这个可以滑动切换图片的界面,我们很自然就会想到ViewPager控件。

2、需要去考虑它的伪循环(其实只是滑到末尾图片再切换到开始图片,给人一种"无限循环"的错觉),做过GalleyView画廊效果的朋友应该很熟悉,当我们滑到画廊到底端,如果想看第一张图片需要再重新滑回去,那么这样给用户的体验就不好,所以我们会在适配器Adapter的getCount()方法里,返回一个很大的数值,让它能够"无限循环"。不清楚的朋友也没关系,下面代码会详细提到。

3、就是考虑它的自动滑动效果,那么很简单的就会去想到定时器,每隔几秒让它自动滑动一次,再通过配合ViewPager的设置当前页面setCurrentItem就可以达到我们想要的效果。

4、最后就是需要考虑到细节方面的东西了,如何让画面滑动配合底部的小圆圈点,我们在做定时器操作的时候,无限循环肯定是一个while永true的状态,当我们切换退出当前界面的时候,这个定时器循环要怎么处理。

好了,考虑好实现原理和流程,我们就可以上手写代码了。

1、首先先来分析下布局:

上面截图说的很详细了,这里直接上代码:

布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="150dp" />
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/viewpager"
        android:background="#33000000"
        android:orientation="vertical"
        android:padding="5dp" >
 
        <TextView
            android:id="@+id/tv_bannertext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="5dp"
            android:text="我是第一个广告语"
            android:textColor="@android:color/white" />
 
        <LinearLayout
            android:id="@+id/points"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>
    </LinearLayout>
 
</RelativeLayout>

然后是小圆圈的样式,这里有2个xml,一个是选择状态,一个是空白状态

小圆圈正常状态

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
    android:shape="oval" >
 
    <corners android:radius="0.5dp" />
 
    <solid android:color="#55000000" />
 
</shape>

小圆圈选中状态

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
    android:shape="oval" >
 
    <corners android:radius="0.5dp" />
 
    <solid android:color="#AAFFFFFF" />
 
</shape>

小圆圈背景效果

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
 
    <item android:drawable="@drawable/point_bg_enable" android:state_enabled="true"></item>
    <item android:drawable="@drawable/point_bg_normal" android:state_enabled="false"></item>
 
</selector>

2、ViewPager适配器

既然我们使用到了VierPager,那么必须要给它设置一个适配器来装载我们所要展示的广告图,这里需要注意的是getCount()这个方法,正常情况下,我们让它返回的是数据源的长度大小,但这里我们需要实现"无限循环"的效果,这么我们可以返回一个比较大的是比如:Integer.MAX_VALUE,这个数值可是20亿,用户再怎么滑到也不会滑到上亿次级别的吧。然后避免出现空指针异常,我们在下面addView和removeView的时候就不能再直接使用position去索引资源了,我们应该取余item的总数量,这样索引位置就不会超过资源数据的数量,例如1%777=1,1%999=1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.lcw.rabbit.banner;
 
import java.util.List;
 
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
 * ViewPager适配器
 * @author Rabbit_Lee
 *
 */
public class BannerAdapter extends PagerAdapter {
 
    //数据源
    private List<ImageView> mList;
 
    public BannerAdapter(List<ImageView> list) {
        this.mList = list;
    }
 
    @Override
    public int getCount() {
        //取超大的数,实现无线循环效果
        return Integer.MAX_VALUE;
    }
 
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }
 
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mList.get(position%mList.size()));
        return mList.get(position%mList.size());
    }
 
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mList.get(position%mList.size()));
    }
 
}

3、主代码

首先先说下小圆圈点的实现,这里有2种方式,一种是直接在广告图上"画死",这种方法耗时耗力而且维护起来很不灵活,所以我们使用第二种方式动态生成,根据广告图的资源长度在给定的LinearLayout里去添加圆圈点View。然后我们需要给它一个pointIndex标志位,用它来记录当前所在的页面位置,初始为0,再每次滑动的时候根据这个标志位来切换小圆圈的状态。

再来说下我们最开始的页面位置,我们不可以设置为0(第一页),如果我们设置为0,那么便不能向左滑动了。由于我们在适配器的getCount返回了Integer.MAX_VALUE ,我们可以取它的中间点来作为起始点,用setCurrentItem来出发VierPager的监听器里的onPageSelected的方法,那么左右就都可以滑动了。

最后就是定时器SystemClock了,我们这里开辟了一条新的线程通过while永true来达到这个效果,让其每隔2秒执行一次设置当前页面的动作,每次只需要简单设置页面+1即可,最后要留意的是我们需要给这个定时器设定一个开关,在我们切换退出该页面的时候要停止掉定时器的操作,也就是去重写我们的onDestroy方法,这里把开关关掉即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.lcw.rabbit.banner;
 
import java.util.ArrayList;
import java.util.List;
 
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
 
public class MainActivity extends Activity {
 
    // 声明控件
    private ViewPager mViewPager;
    private List<ImageView> mlist;
    private TextView mTextView;
    private LinearLayout mLinearLayout;
 
    // 广告图素材
    private int[] bannerImages = { R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4 };
    // 广告语
    private String[] bannerTexts = { "因为专业 所以卓越", "坚持创新 行业领跑", "诚信 专业 双赢", "精细 和谐 大气 开放" };
 
    // ViewPager适配器与监听器
    private BannerAdapter mAdapter;
    private BannerListener bannerListener;
 
    // 圆圈标志位
    private int pointIndex = 0;
    // 线程标志
    private boolean isStop = false;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initAction();
 
        // 开启新线程,2秒一次更新Banner
        new Thread(new Runnable() {
 
            @Override
            public void run() {
                while (!isStop) {
                    SystemClock.sleep(2000);
                    runOnUiThread(new Runnable() {
 
                        @Override
                        public void run() {
                            mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
                        }
                    });
                }
            }
        }).start();
    }
 
    /**
     * 初始化事件
     */
    private void initAction() {
        bannerListener = new BannerListener();
        mViewPager.setOnPageChangeListener(bannerListener);
        //取中间数来作为起始位置
        int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mlist.size());
        //用来出发监听器
        mViewPager.setCurrentItem(index);
        mLinearLayout.getChildAt(pointIndex).setEnabled(true);
    }
 
    /**
     * 初始化数据
     */
    private void initData() {
        mlist = new ArrayList<ImageView>();
        View view;
        LayoutParams params;
        for (int i = 0; i < bannerImages.length; i++) {
            // 设置广告图
            ImageView imageView = new ImageView(MainActivity.this);
            imageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            imageView.setBackgroundResource(bannerImages[i]);
            mlist.add(imageView);
            // 设置圆圈点
            view = new View(MainActivity.this);
            params = new LayoutParams(5, 5);
            params.leftMargin = 10;
            view.setBackgroundResource(R.drawable.point_background);
            view.setLayoutParams(params);
            view.setEnabled(false);
 
            mLinearLayout.addView(view);
        }
        mAdapter = new BannerAdapter(mlist);
        mViewPager.setAdapter(mAdapter);
    }
 
    /**
     * 初始化View操作
     */
    private void initView() {
        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        mTextView = (TextView) findViewById(R.id.tv_bannertext);
        mLinearLayout = (LinearLayout) findViewById(R.id.points);
    }
 
    //实现VierPager监听器接口
    class BannerListener implements OnPageChangeListener {
 
        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
 
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }
 
        @Override
        public void onPageSelected(int position) {
            int newPosition = position % bannerImages.length;
            mTextView.setText(bannerTexts[newPosition]);
            mLinearLayout.getChildAt(newPosition).setEnabled(true);
            mLinearLayout.getChildAt(pointIndex).setEnabled(false);
            // 更新标志位
            pointIndex = newPosition;
 
        }
 
    }
 
    @Override
    protected void onDestroy() {
        // 关闭定时器
        isStop = true;
        super.onDestroy();
    }
 
}

android-自定义广告轮播Banner(无限循环实现)的更多相关文章

  1. 安卓开发笔记——自定义广告轮播Banner(实现无限循环)

    关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...

  2. [android] 轮播图-无限循环

    实现无限循环 在getCount()方法中,返回一个很大的值,Integer.MAX_VALUE 在instantiateItem()方法中,获取当前View的索引时,进行取于操作,传递进来的int ...

  3. android中广告轮播图总结

    功能点:无限轮播.指示点跟随.点击响应.实现思路: 1.指示点跟随,指示点通过代码动态添加,数量由图片数量决定. 在viewpager的页面改变监听中,设置点的状态选择器enable,当前页时,set ...

  4. SuperIndicator 专做轮播图库,没有之一,支持轮播图无限循环

    github地址:https://github.com/hejunlin2013/SuperIndicator SuperIndicator a superindicatorlibray for vi ...

  5. Android真正意义上的无限轮播Banner

    在android开发的时候,经常会使用到轮播图,对于这种效果,一般情况下,我们都会使用一种叫做ViewPager的来实现. 传统的实现逻辑是自定义一个View继承ViewPager,在适配器中 将co ...

  6. 自定义完美的ViewPager 真正无限循环的轮播图

    网上80%的思路关于Android轮播图无限循环都是不正确的,不是真正意义上的无限循环, 其思路大多是将ViewPager的getCount方法返回值设置为Integer.MAX_VALUE, 然后呢 ...

  7. 自定义View(二)ViewPage广告轮播

    自定义View的第二个学习案例,使用ViewPage实现广告轮播,通过组合现有的View实现效果如下: 有关ViewPage使用可以学习谷歌官方API,和训练案例: 1.使用ViewPage实现屏幕滑 ...

  8. android 使用图片轮播图---banner 使用

    转自:https://github.com/youth5201314/banner 使用步骤 Step 1.依赖banner Gradle dependencies{ compile 'com.you ...

  9. android 项目学习随笔十六( 广告轮播条播放)

    广告轮播条播放 if (mHandler == null) {//在此初始化mHandler , 保证消息不重复发送 mHandler = new Handler() { public void ha ...

随机推荐

  1. B+树的插入、删除(附源代码)

    B+ Tree Index B+树的插入 B+树的删除 完整测试代码 Basic B+树和B树类似(有关B树:http://www.cnblogs.com/YuNanlong/p/6354029.ht ...

  2. Express与NodeJs创建服务器的两种方法

    NodeJs创建Web服务器 var http = require('http'); var server = http.createServer(function(req, res) { res.w ...

  3. 网络攻击技术开篇——SQL Injection

    本文转自: http://www.cnblogs.com/rush/archive/2011/12/31/2309203.html 1.1.1 摘要 日前,国内最大的程序员社区CSDN网站的用户数据库 ...

  4. iOS Touch ID 身份认证

    iOS Touch ID 身份认证 iOS 8 及以后录了指纹的设备可以使用 touch ID 进行身份认证,指纹符合录入的指纹才能认证成功. 步骤 导入 LocalAuthentication 框架 ...

  5. Java安装

    java特点:跨平台.简单.面向对像编译后解释再运行安装JDK 环境变量的配置:JAVA_HOME:JDK的根目录====C:\Program Files\Java\jdk1.7.0_25Path:J ...

  6. css控制图片与文字对齐

    文字旁边搭配图片时,发现图片比文字靠上,原来默认的情况是图片顶对齐而文字底对齐,通过设置css属性可以使得图片与文字对齐. 设置各对象的vertical-align属性,属性说明:baseline-将 ...

  7. CREELINKS平台_处理器CeCcp资源使用说明(CeCcp的配置与使用)

    0x00 CREELINKS平台简介     CREELINKS(创e联)是由大信科技有限公司研发,集合软硬件.操作系统.数据云储存.开发工具于一体,用于物联网产品的设计.研发与生产的平台.    平 ...

  8. Sqlite 帮助类 SQLiteHelper

    ///源码下载地址:http://download.csdn.net/detail/kehaigang29/8836171 ///dll下载地址:http://download.csdn.net/de ...

  9. 各种ORM框架对比(理论篇,欢迎来观摩)

    各种ORM框架对比 目前框架有以下 PetaPoco Dapper.NET Massive Simple.Data Chain PetaPoco 轻量级,以前单文件,目前有维护形成项目级别,适合多个数 ...

  10. 【Zookeeper】源码分析之网络通信(二)

    一.前言 前面介绍了ServerCnxn,下面开始学习NIOServerCnxn. 二.NIOServerCnxn源码分析 2.1 类的继承关系 public class NIOServerCnxn ...