用ViewPager实现无缝循环广告位

Android上的缝循环广告位实现方法似乎有很多种方法,还有的大神用RecyclerView实现了。但是,我试了一下用ViewPager,好像这个更简便一点。
先看一下效果图:


ViewPagerAD.gif

demo中用到了:

  1. Gson 一个谷歌的Json解析库,速度快,很好用。
  2. Glide 用于加载图片的第三方库,如丝般顺畅。
  3. Volley 网络请求的第三方库,比较早就有了,现在仍很多人用。

如果对以上这三个库不了解的话,建议先去看看。

初始化那些什么的就不说了,我们直接说重点的。

布局

很简单,ViewPager+LinearLayout。底下的LinearLayout是用来显示圆点的。

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="com.sonnyzoom.viewpagerad.MainActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="180dp" />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" />

</LinearLayout>
实现过程

既然用到ViewPager,肯定需要一个适配器PagerAdapter:

    class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return Integer.MAX_VALUE;  //最大值,可以认为无限大,反正你划不到尽头就行了
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            //在0~imageViewList.size()之间循环
            int index = position % imageViewList.size();

            imageViewList.get(index).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //处理图片点击事件....
                    Log.e("点击图片:",position % imageViewList.size()+"");
                }
            });

            if (imageViewList.size() > 0) {
                View view = imageViewList.get(index);
                if (container.equals(view.getParent())) {
                    container.removeView(view);
                }
                container.addView(view);
                return view;
            }


            return null;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            int index = position % imageViewList.size();
            container.removeView(imageViewList.get(index));
        }

    }

然后用Volley请求网络,拿到数据:

        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        StringRequest request = new StringRequest(URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                //拿到网络请求的数据
                doSomething(s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e(TGA, "", volleyError);
            }
        });
        requestQueue.add(request);

用Gson解析,得到图片的Url的List,即imgs。同时new一个ImageView,用Glide加载后添加到image的List即imageViewList,ImageView dot为小圆点。设置适配器,启动线程:

    private void doSomething(String s) {

        DataInfo info = gson.fromJson(s, DataInfo.class);
        DataInfo.DataEntity entity = info.getData();
        imgs = entity.getImgs();

        for (int i = 0; i < imgs.size(); i++) {
            ImageView imageView = new ImageView(this);
            imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            Glide.with(this)
                    .load(imgs.get(i).getPic_url_yasha())
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(imageView);
            imageViewList.add(imageView);
            ImageView dot = new ImageView(this);
            dot.setImageResource(R.drawable.point_normal);
            dot.setPadding(10, 5, 10, 5);
            linearLayout.addView(dot);

        }

        MyAdapter adapter = new MyAdapter();
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(currentIndex);
        viewPager.addOnPageChangeListener(this);

        handler.post(r);

    }

用于循环播放的线程:

    private Handler handler = new Handler();
    Runnable r = new Runnable() {
        @Override
        public void run() {

            if (isCyclical) {
                if (System.currentTimeMillis() - lastTime > 2000) {
                    currentIndex++;
                    viewPager.setCurrentItem(currentIndex);
                    lastTime = System.currentTimeMillis();
                }
                //递归循环,图片切换速度3秒一张
                handler.postDelayed(r, 3000);
            }
        }
    };

伴随图片切换而切换的底部小圆点:

    private void setCurrentSelector(int index) {
        for (int i = 0; i < linearLayout.getChildCount(); i++) {
            ImageView child = (ImageView) linearLayout.getChildAt(i);
            if (i == index) {
                child.setImageResource(R.drawable.point_selected);
            } else {
                child.setImageResource(R.drawable.point_normal);
            }
        }
    }

最后在onDestroy()方法里面把循环线程停掉,不然你退出程序它还在运行:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isCyclical = false; //Activity退出后,图片循环线程停止
    }

主要实现过程就酱紫~

附上全部代码:

package com.sonnyzoom.viewpagerad;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.gson.Gson;
import com.sonnyzoom.viewpagerad.bean.DataInfo;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    public static final String URL = "http://spark.api.xiami.com/sdk?v=sdk&method=mobile.sdk-image&device_id=de717e77-6330-3c13-b601-e3c6228d4f16&api_key=bbf59448b1d2a0254d033bfe3b4d8a30&call_id=1443063251736&api_sig=5c29b6c2ffed24d7f5b481d7deb0511e";
    public static final String TGA = "MainActivity";
    private ViewPager viewPager;
    private LinearLayout linearLayout;
    private List<DataInfo.DataEntity.ImgsEntity> imgs;
    private List<ImageView> imageViewList;

    private int currentIndex=300; //初始值可以设置大一点,防止左划到尽头。
    private long lastTime;

    private Gson gson;

    private boolean isCyclical = true;

    private Handler handler = new Handler();
    Runnable r = new Runnable() {
        @Override
        public void run() {

            if (isCyclical) {
                if (System.currentTimeMillis() - lastTime > 2000) {
                    currentIndex++;
                    viewPager.setCurrentItem(currentIndex);
                    lastTime = System.currentTimeMillis();
                }
                //递归循环,图片切换速度3秒一张
                handler.postDelayed(r, 3000);
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        linearLayout = (LinearLayout) findViewById(R.id.linearLayout);

        imgs = new ArrayList<>();
        imageViewList = new ArrayList<>();
        gson = new Gson();

        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        StringRequest request = new StringRequest(URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                //拿到网络请求的数据
                doSomething(s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e(TGA, "", volleyError);
            }
        });
        requestQueue.add(request);

    }

    private void doSomething(String s) {

        DataInfo info = gson.fromJson(s, DataInfo.class);
        DataInfo.DataEntity entity = info.getData();
        imgs = entity.getImgs();

        for (int i = 0; i < imgs.size(); i++) {
            ImageView imageView = new ImageView(this);
            imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            Glide.with(this)
                    .load(imgs.get(i).getPic_url_yasha())
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(imageView);
            imageViewList.add(imageView);
            ImageView dot = new ImageView(this);
            dot.setImageResource(R.drawable.point_normal);
            dot.setPadding(10, 5, 10, 5);
            linearLayout.addView(dot);

        }

        MyAdapter adapter = new MyAdapter();
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(currentIndex);
        viewPager.addOnPageChangeListener(this);

        handler.post(r);

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(final int position) {
        Log.e("位置:", position + "");
        currentIndex = position;
        int index = position % imageViewList.size();
        setCurrentSelector(index);
        lastTime = System.currentTimeMillis();
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    private void setCurrentSelector(int index) {
        for (int i = 0; i < linearLayout.getChildCount(); i++) {
            ImageView child = (ImageView) linearLayout.getChildAt(i);
            if (i == index) {
                child.setImageResource(R.drawable.point_selected);
            } else {
                child.setImageResource(R.drawable.point_normal);
            }
        }
    }


    class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return Integer.MAX_VALUE;  //最大值,可以认为无限大,反正你划不到尽头就行了
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            //在0~imageViewList.size()之间循环
            int index = position % imageViewList.size();

            imageViewList.get(index).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //处理图片点击事件....
                    Log.e("点击图片:",position % imageViewList.size()+"");
                }
            });

            if (imageViewList.size() > 0) {
                View view = imageViewList.get(index);
                if (container.equals(view.getParent())) {
                    container.removeView(view);
                }
                container.addView(view);
                return view;
            }


            return null;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            int index = position % imageViewList.size();
            container.removeView(imageViewList.get(index));
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isCyclical = false; //Activity退出后,图片循环线程停止
    }
}

源码已上传:Github
有什么错误或者建议可以在评论下面留言。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 效果图 一、ViewPager填充图片 1.1 布局中申明 由于是显示广告条,所以高度要固定住 1.2 代码中设置...
    笑说余生阅读 9,791评论 9 44
  • 我只是找个地方写信给自己,有些话只想说给自己听,我把那个自己叫做小凡, 小凡有时候是男生,有时候是女生,有时候是个...
    令狐书生阅读 271评论 0 0
  • 家:每次回到大海都像是回家,接受给我的挑战,不断蜕变,在大海面前毫无保留的做真实的自己,每次离家都是为了更好的回家...
    Moana雪阅读 684评论 14 4
  • 他的灵魂涂抹在素白瓷器上 门前的柳很早就死了 说一句 “终于可以卧下” 黑色的泥土捣成鹅黄的叶 干了加水,薄了加光...
    我是不是蝎大人阅读 109评论 4 1