Android 無限循環的廣告輪播圖

上一篇文章講了自定義控件的是關於輪播圖的,這張我們就來說一下輪播圖的實現。輪播圖的實現用到的控件是ViewPager,關於ViewPager的懶加載機制我在前面的文章中已經講過,大家如果有興趣的話可以去看看。關於無限循環的廣告輪播圖真的是可以無限循環嗎?答案是不可能的。因爲我們都清楚我們的無限輪播不過是將展示的條目數設置的很大,給我們的感覺就是一直在循環展示。如何設置呢?下面我就來一一爲大家解析一下。
請先看實現的效果
這裏寫圖片描述
如果實現輪播我們離不了一個適配器就是PagerAdapter,我們如果繼承這個適配器一般會重寫一些方法,我們先了解一下這個適配器裏面的這些方法。
public Object instantiateItem(ViewGroup container, int position)
這個方法就是用來獲得指定位置要顯示的View,並添加到container這個容器裏面。相當於我們一般的Adapter裏面的public View getView(int position, View convertView, ViewGroup parent) 這個方法。有創建的就會有銷燬的public void destroyItem(ViewGroup container, int position, Object object)這個方法的調用就是銷燬頁面的
下面我們來看一下日誌

custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->
custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->
custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->
custom.lyxrobert.com.customcontrols I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@32bc79af time:28825056
custom.lyxrobert.com.customcontrols D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
custom.lyxrobert.com.customcontrols I/System.out: destroyItem------------->
custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->
custom.lyxrobert.com.customcontrols D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
custom.lyxrobert.com.customcontrols I/System.out: destroyItem------------->
custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->
custom.lyxrobert.com.customcontrols D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
custom.lyxrobert.com.customcontrols I/System.out: destroyItem------------->
custom.lyxrobert.com.customcontrols I/System.out: instantiateItem------------->

我們可以看到剛開始的時候會走instantiateItem這個方法,這是因爲當應用開啓的時候首先會去加載界面也就是相當於activity裏面的onCreate方法(生命週期)。那麼爲什麼會連續出現三個呢?這就是懶加載機制了。默認的爲1,實際上是左右各一共3個界面,銷燬的界面是按照先進先銷燬的跟隊列一樣因爲container裏面只能容納3個,還想進來怎麼辦?只能先移除一個才能把另一個加進來。它是銷燬一個再新建一個,只有先騰出位置才能進入的。public boolean isViewFromObject(View view, Object object)這個方法是確定一個頁面視圖是否關聯到一個特定的對象。通常我們默認的設置爲return view == object;這個其實是跟你調用public Object instantiateItem(ViewGroup container, int position)這個方法相關聯的,當你向容器裏面添加一個對象是都會調用public boolean isViewFromObject(View view, Object object)這個方法進行判斷,這個object對象就是開始調用instantiateItem這個方法添加進去的。

@Override
    public Object instantiateItem(ViewGroup container, int position) {
        System.out.println("instantiateItem------------->");
        final int pos = position % adList.size();
        ImageView imageView = new ImageView(context);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        imageView.setLayoutParams(params);
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageLoader.displayImage(adList.get(pos), imageView, options);
        container.addView(imageView, ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        return imageView;
    }

    @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);
    }

添加的時候是一個對象而移除的時候是View這就不難理解了吧。
扯了這麼多還沒有說無限循環的事呢。

@Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

Integer.MAX_VALUE最大爲2的31-1次方,也就是2147483647,想想這麼大的數,我們一般規定的是2—3秒,想想這需要多少秒才能達到這個數,而且是你的手機在不斷電應用不殺死的情況下,你這一生都不可能看到的更何況你的手機的壽命更短呢。人家既然能讓你做無限輪播雖然是假的但是跟真的也就沒啥區別了。
上面的是向左划動可以無限循環,如果想向右划動怎麼辦呢?其實很簡單,我們向左一般是自動輪播的,向右的話就是需要自己手動去划動。如果讓你用手不停地划動屏幕你樂意嗎?即使你有那個興趣去嘗試,你不心疼你的手機屏幕嗎?很多人最多也就劃二三十下就沒興趣了。如何設置向右划動的呢?如果我們默認的開始頁面是0的話向右划動的話就會出現-1的情況,但是-1的出現是不允許的,怎麼辦?我們就要從一些比0大很多的數開始作爲起始點。一般建議以集合的大小去乘以一個你認爲比較不錯的數比如100,1000,(負數和帶有小數點的數除外),這樣做的目的就是爲了能夠讓滾動起始頁面爲第一個頁面。設置實現爲vp_shuffling.setCurrentItem(size * 1000, false);
實現了圖片的滾動還想實現點的切換怎麼辦?如果直接在佈局裏面寫死幾個點然後根據位置再將點切換爲選中的狀態,這樣的話恐怕不是每個人想要的,一般都是在佈局裏面設置一個父控件LinearLayout下面看看佈局的實現
佈局裏面使用了一個插值器,關於插值器有以下幾個
accelerate_decelerate_interpolator: 開始與結束的地方速率改變比較慢,在中間的時候加速
這裏寫圖片描述
accelerate_interpolator:開始的地方速率改變比較慢,然後開始加速
這裏寫圖片描述
anticipate_interpolator:開始的時候向後然後向前
這裏寫圖片描述
anticipate_overshoot_interpolator:開始的時候向後然後向前甩一定值後返回最後的值
這裏寫圖片描述
bounce_interpolator動畫結束的時候彈起
這裏寫圖片描述
cycle_interpolator:循環播放特定的次數,速率改變沿着正弦曲線
這裏寫圖片描述
decelerate_interpolator:在開始的地方快然後慢
這裏寫圖片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:lyxrobert="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <custom.lyxrobert.com.customcontrols.view.CustomLayout
    android:layout_width="match_parent" android:layout_height="wrap_content"
    lyxrobert:rario="1.7">
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_shuffling"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
         />

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:text="123"
            android:gravity="center"
            android:textColor="@android:color/white"
            android:layout_gravity="bottom"
            android:background="#99000000"/>
        <LinearLayout
            android:id="@+id/layout_point"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_marginBottom="15dp"
            android:gravity="right|center"
            android:orientation="horizontal" />
</custom.lyxrobert.com.customcontrols.view.CustomLayout>

</LinearLayout>

再來看看類是如何實現的

package custom.lyxrobert.com.customcontrols.activities;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import custom.lyxrobert.com.customcontrols.R;
import custom.lyxrobert.com.customcontrols.adapter.BannerAdapter;

public class MainActivity extends Activity {
    private ViewPager vp_shuffling;
    private List<String> mADParseArray;
    private final int HOME_AD_RESULT = 1;
    private TextView tv_content;
    private LinearLayout dotLayout; // 圈圈 佈局
    private Context mContext;
    private String[] content;
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                // 廣告
                case HOME_AD_RESULT:
                    vp_shuffling.setCurrentItem(vp_shuffling.getCurrentItem() + 1,
                            true);
                    break;
            }
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mContext = MainActivity.this;
        vp_shuffling = (ViewPager)findViewById(R.id.vp_shuffling);
        tv_content = (TextView) findViewById(R.id.tv_content);
        dotLayout = (LinearLayout)findViewById(R.id.layout_point);
        mADParseArray = new ArrayList<String>();
        mADParseArray
                .add("http://m.easyto.com/m/zhulifuwu_banner.jpg");
        mADParseArray
                .add("http://m.easyto.com/m/japan/images/banner_3y_new.jpg");
        mADParseArray
                .add("http://m.easyto.com/m/japan/images/banner_5y_new.jpg");
        final int size = mADParseArray.size();
        content = new String[]{"海外助理服務,搶先體驗","日本個籤1799元三年多次","日本個籤1999元五年多次"};
        vp_shuffling.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                refreshPoint(position % size);
                if (mHandler.hasMessages(HOME_AD_RESULT)) {
                    mHandler.removeMessages(HOME_AD_RESULT);
                }
                mHandler.sendEmptyMessageDelayed(HOME_AD_RESULT, 3000);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                if (ViewPager.SCROLL_STATE_DRAGGING == arg0
                        && mHandler.hasMessages(HOME_AD_RESULT)) {
                    mHandler.removeMessages(HOME_AD_RESULT);
                }
            }
        });
        BannerAdapter adapter = new BannerAdapter(mContext, mADParseArray);
        vp_shuffling.setAdapter(adapter);

        initPointsLayout(size);
        vp_shuffling.setCurrentItem(size * 1000, false);
        // 自動輪播線程
        mHandler.sendEmptyMessageDelayed(HOME_AD_RESULT, 3000);
    }
    private void initPointsLayout(int size) {
        for (int i = 0; i < size; i++) {
            ImageView image = null;
            if (mContext != null) {
                image = new ImageView(mContext);
            }
            float denstity = getResources().getDisplayMetrics().density;
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    (int) (6 * denstity), (int) (6 * denstity));
            params.leftMargin = (int) (2 * denstity);
            params.rightMargin = (int) (2 * denstity);
            image.setLayoutParams(params);
            if (i == 0) {
                image.setBackgroundResource(R.drawable.dot_enable);
            } else {
                image.setBackgroundResource(R.drawable.dot_normal);
            }
            dotLayout.addView(image);
        }
    }

    private void refreshPoint(int position) {
        if (dotLayout != null) {
            for (int i = 0; i < dotLayout.getChildCount(); i++) {
                if (i == position) {
                    dotLayout.getChildAt(i).setBackgroundResource(
                            R.drawable.dot_enable);
                    tv_content.setText(content[position]);
                } else {
                    dotLayout.getChildAt(i).setBackgroundResource(
                            R.drawable.dot_normal);
                }
            }
        }
    }

}

還是上源碼吧
點擊下載源碼
如有問題歡迎留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章