Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android輪播圖原理思路分析+實現方案

Android輪播圖原理思路分析+實現方案

編輯:關於Android編程

?ListView的headerView設置為輪播圖之後結合上/下拉刷新/加載的模式成為現在大多數APP的一個必須具備的功能,對於許多初學者來說想要實現輪播圖這樣一個集線程睡眠、自動處理、替換過程中刷新UI界面的組合功能非常困難,沒有思路,感覺無從下手,去搜索各種實現方案,發現目前充斥著大量的類似於使用棄用組件Gallery這樣的例子。
? 本篇博客將通過分析輪播圖的各個注意事項及實現思路來實現一個簡易的輪播圖。
? 首先看下一下效果圖;
需求: 1.輪播,如輪播四張圖:到第四張之後不會回到第一張而是繼續向下一張切換;
2.初始狀態即可向前滑動
3.輪播過程中會有狀態切換以白點和黑點的方式呈現;

這裡寫圖片描述
這裡寫圖片描述

ps:這裡的魂斗羅見到有沒有熱血沸騰,情懷所在;

實現步驟:
一、輪播圖部分采用的是ViewPager顯示Layout布局,替換圖片的方式
1.為了讓圖片滑到最後一張不是以翻頁的形式回到首頁,getCount方法返回的是int最大值,這樣就會有很多頁;
2.由於getCount方法返回整型最大值,所以使用的pZ喎?/kf/ware/vc/" target="_blank" class="keylink">vc2l0aW9ussnTw8ih0+C1xLzGy+O3vbeoo6zL5Mi7cG9zaXRpb2674dK71rHU9rzTo6y1q8rHz9TKvrXEyv2+3cq81tXOqrnMtqjK/cG/o7s8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> package com.wu.rotateimgdemo; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import java.util.List; /** * Created by wubihang on 16/9/12. */ public class RotateVpAdapter extends PagerAdapter{ private List datas; private Context context; private LayoutInflater inflater; public RotateVpAdapter(Context context) { this.context = context; inflater = LayoutInflater.from(context); } public void setDatas(List datas) { this.datas = datas; notifyDataSetChanged(); } @Override public int getCount() { // 為了讓ViewPager到最後一頁不會像翻書一樣回到第一頁 // 設置頁數為int最大值,這樣向下滑動永遠都是下一頁 return datas == null ? 0 : Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { // position是int最大值所以這裡可能是幾百甚至上千,因此取余避免數組越界 int newPosition = position % datas.size(); View convertView = inflater.inflate(R.layout.item_vp, container, false); ImageView imageView = (ImageView) convertView.findViewById(R.id.item_iv); TextView textView = (TextView) convertView.findViewById(R.id.item_tv); textView.setText("文字內容" + newPosition); imageView.setImageResource(datas.get(newPosition).getImgId()); container.addView(convertView); return convertView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { } }

二、設置輪播的線程
1.輪播采用Handler對象的postDelayed方法,發送一個延時的任務;
任務的內容是每隔固定時間讓ViewPager當前頁自增1,如果處於輪播狀態再次延時執行該任務,這樣只要輪播狀態isRotate為true,就像死循環一樣一直執行此輪播任務;

/**
     * 開始輪播
     */
    private void startRotate() {
        rotateRunnable = new Runnable() {
            @Override
            public void run() {
                int nowIndex = viewPager.getCurrentItem();
                viewPager.setCurrentItem(++nowIndex);
                if (isRotate) {
                    handler.postDelayed(rotateRunnable, TIME);
                }
            }
        };
        handler.postDelayed(rotateRunnable, TIME);
    }

在onPause和onResume裡對於輪播狀態進行了處理

@Override
    protected void onResume() {
        super.onResume();
        isRotate = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isRotate = false;
    }

三、設置輪播狀態切換的小圓點
1.設置的方式是動態的,有多少張輪播圖就循環加入多少個小圓點;
2.將position==0時的小圓點設置為黑色,默認選中第一張,剩下的設置為白色;
這裡的mipmap是我自己做的兩張黑色的和白色的小圓點圖片;

    /**
     * 添加輪播切換小點
     */
    private void addPoints() {
        // 有多少張圖加載多少個小點
        for (int i = 0; i < datas.size(); i++) {
            ImageView pointIv = new ImageView(this);
            pointIv.setPadding(5,5,5,5);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20,20);
            pointIv.setLayoutParams(params);

            // 設置第0頁小點的為灰色
            if (i == 0) {
                pointIv.setImageResource(R.mipmap.point_grey);
            } else {
                pointIv.setImageResource(R.mipmap.point_white);
            }
            pointLl.addView(pointIv);
        }
    }

四、設置ViewPager頁切換時小圓點的顏色跟著改變
1.當頁切換時,獲取所有的小圓點,將他們都設置為白色;
2.獲取當前頁的小圓點,將它設置為黑色;

private void changePoints() {
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (isRotate) {
                    // 把所有小點設置為白色
                    for (int i = 0; i < datas.size(); i++) {
                        ImageView pointIv = (ImageView) pointLl.getChildAt(i);
                        pointIv.setImageResource(R.mipmap.point_white);
                    }
                    // 設置當前位置小點為灰色
                    ImageView iv = (ImageView) pointLl.getChildAt(position % datas.size());
                    iv.setImageResource(R.mipmap.point_grey);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

這樣簡單的完成了一個ViewPager實現的輪播線程;

分析及實現過程完畢,下面貼上全部代碼!

1.布局文件

activity_main.xml
分別是裝載輪播圖的ViewPager和裝載小圓點的容器;





    <framelayout android:layout_height="300dp" android:layout_width="match_parent">

        

        
    </framelayout>



ViewPager的頁布局
item_vp.xml
分別是顯示輪播圖的ImageView和顯示上面文字的TextView;


<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">


    

    

</framelayout>

2.數據實體類
這裡運用的是本地圖片,因此使用的是imgId;
如果網絡圖片也可以加入,將圖片源更改即可;

package com.wu.rotateimgdemo;

import java.io.Serializable;

/**
 * Created by wubihang on 16/9/12.
 */
public class RotateBean implements Serializable{

    private int imgId;
    private String imgUrl;

    public RotateBean() {
    }

    public RotateBean(String imgUrl) {
        this.imgUrl = imgUrl;
    }

    public RotateBean(int imgId) {
        this.imgId = imgId;
    }

    public RotateBean(int imgId, String imgUrl) {
        this.imgId = imgId;
        this.imgUrl = imgUrl;
    }

    public int getImgId() {
        return imgId;
    }

    public void setImgId(int imgId) {
        this.imgId = imgId;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }
}

3.適配器
適配器部分需要注意:
1)getCount的返回值
2)使用時position取余的運用(防止數組越界)

package com.wu.rotateimgdemo;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by wubihang on 16/9/12.
 */
public class RotateVpAdapter extends PagerAdapter{

    private List datas;
    private Context context;
    private LayoutInflater inflater;

    public RotateVpAdapter(List datas, Context context) {
        this.datas = datas;
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public RotateVpAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public void setDatas(List datas) {
        this.datas = datas;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        // 為了讓ViewPager到最後一頁不會像翻書一樣回到第一頁
        // 設置頁數為int最大值,這樣向下滑動永遠都是下一頁
        return datas == null ? 0 : Integer.MAX_VALUE;
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // position是int最大值所以這裡可能是幾百甚至上千,因此取余避免數組越界
        int newPosition = position % datas.size();
        View convertView = inflater.inflate(R.layout.item_vp, container, false);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.item_iv);
        TextView textView = (TextView) convertView.findViewById(R.id.item_tv);
        textView.setText("文字內容" + newPosition);
        imageView.setImageResource(datas.get(newPosition).getImgId());

        container.addView(convertView);
        return convertView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

    }
}

4.Activity部分,此部分代碼比較多,請閱讀時仔細梳理;

package com.wu.rotateimgdemo;

import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;

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

public class MainActivity extends AppCompatActivity {

    private static final int TIME = 3000;

    private ViewPager viewPager;
    private LinearLayout pointLl;// 輪播狀態改變的小圓點容器
    private List datas;
    private RotateVpAdapter vpAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = (ViewPager) findViewById(R.id.rotate_vp);
        pointLl = (LinearLayout) findViewById(R.id.rotate_point_container);

        buildDatas();// 構造數據
        vpAdapter = new RotateVpAdapter(datas, this);
        viewPager.setAdapter(vpAdapter);
        // ViewPager的頁數為int最大值,設置當前頁多一些,可以上來就向前滑動
        // 為了保證第一頁始終為數據的第0條 取余要為0,因此設置數據集合大小的倍數
        viewPager.setCurrentItem(datas.size() * 100);

        // 開始輪播
        handler = new Handler();
        startRotate();
        // 添加輪播小點
        addPoints();
        // 隨著輪播改變小點
        changePoints();
    }

    private void changePoints() {
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (isRotate) {
                    // 把所有小點設置為白色
                    for (int i = 0; i < datas.size(); i++) {
                        ImageView pointIv = (ImageView) pointLl.getChildAt(i);
                        pointIv.setImageResource(R.mipmap.point_white);
                    }
                    // 設置當前位置小點為灰色
                    ImageView iv = (ImageView) pointLl.getChildAt(position % datas.size());
                    iv.setImageResource(R.mipmap.point_grey);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    /**
     * 添加輪播切換小點
     */
    private void addPoints() {
        // 有多少張圖加載多少個小點
        for (int i = 0; i < datas.size(); i++) {
            ImageView pointIv = new ImageView(this);
            pointIv.setPadding(5,5,5,5);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20,20);
            pointIv.setLayoutParams(params);

            // 設置第0頁小點的為灰色
            if (i == 0) {
                pointIv.setImageResource(R.mipmap.point_grey);
            } else {
                pointIv.setImageResource(R.mipmap.point_white);
            }
            pointLl.addView(pointIv);
        }
    }


    private Handler handler;
    private boolean isRotate = false;
    private Runnable rotateRunnable;

    /**
     * 開始輪播
     */
    private void startRotate() {
        rotateRunnable = new Runnable() {
            @Override
            public void run() {
                int nowIndex = viewPager.getCurrentItem();
                viewPager.setCurrentItem(++nowIndex);
                if (isRotate) {
                    handler.postDelayed(rotateRunnable, TIME);
                }
            }
        };
        handler.postDelayed(rotateRunnable, TIME);
    }

    @Override
    protected void onResume() {
        super.onResume();
        isRotate = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isRotate = false;
    }

    private void buildDatas() {
        datas = new ArrayList<>();
        datas.add(new RotateBean(R.mipmap.big_image));
        datas.add(new RotateBean(R.mipmap.btn_normal));
        datas.add(new RotateBean(R.mipmap.icon_baoman));
        datas.add(new RotateBean(R.mipmap.btn_pressed));
    }
}

本篇博客內容純屬原創,各位隨便使用隨便點評;

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved