1. 程式人生 > >Android輪播圖原理思路分析+實現方案

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

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

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

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

實現步驟:
一、輪播圖部分採用的是ViewPager顯示Layout佈局,替換圖片的方式
1.為了讓圖片滑到最後一張不是以翻頁的形式回到首頁,getCount方法返回的是int最大值,這樣就會有很多頁;
2.由於getCount方法返回整型最大值,所以使用的position採用取餘的計算方法,雖然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<RotateBean> datas; private
Context context; private LayoutInflater inflater; public RotateVpAdapter(Context context) { this.context = context; inflater = LayoutInflater.from(context); } public void setDatas(List<RotateBean> 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和裝載小圓點的容器;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


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

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

        <LinearLayout
            android:id="@+id/rotate_point_container"
            android:layout_width="match_parent"
            android:layout_height="20dp"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="10dp"
            android:orientation="horizontal"/>
    </FrameLayout>


</LinearLayout>

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

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <ImageView
        android:id="@+id/item_iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/item_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:layout_marginBottom="25dp"
        android:textSize="16sp"
        android:textColor="#f03"
        android:layout_marginRight="10dp"
        android:textStyle="bold" />

</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<RotateBean> datas;
    private Context context;
    private LayoutInflater inflater;

    public RotateVpAdapter(List<RotateBean> 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<RotateBean> 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<RotateBean> 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));
    }
}

本篇部落格內容純屬原創,各位隨便使用隨便點評;
祝大家寫程式碼無bug,實現功能思路如飛;

原始碼下載請見下方連結

相關推薦

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

 ListView的headerView設定為輪播圖之後結合上/下拉重新整理/載入的模式成為現在大多數APP的一個必須具備的功能,對於許多初學者來說想要實現輪播圖這樣一個集執行緒睡眠、自動處理、替換過程中重新整理UI介面的組合功能非常困難,沒有思路,感覺無從下手

android 使用banner依賴實現

首先引入輪播圖的一個依賴 compile 'com.hejunlin.superindicatorlibray:superindicatorlibray:1.0.3' 這是這個依賴作者github上的地址https://github.com/hejunlin2013/Su

Android Banner的簡單實現

輪播圖已經出來很長時間了,我也看了很多部落格,看了很多的人程式碼,也有自己寫原生的,也有用第三方框架的,學習安卓有一段時間了,決定寫一寫部落格來記錄自己的安卓學習生涯,不管以前有沒有古人寫過,反正我是這個來者哈哈哈;廢話不多說了,進入正文吧。 Banner的簡

android點的佈局實現

//values.styles.XML下 <style name="image_status_on_style"> <item name="android:layo

原生js實現原理分析

一、輪播圖需求 輪播圖需要實現左右翻頁的無縫連線 需要點選左右切換 需要實現跳轉 顯示當前位置的小圓點 二、輪播圖的原理 1.圖片移動實現原理: 利用浮動將所有所有照片依次排成一行,給這一長串圖片新增一個父級的遮罩,每次只顯示一張圖,其餘的都隱

原生js實現原理

輪播圖的原理1.圖片移動實現原理:利用浮動將所有所有照片依次排成一行,給這一長串圖片新增一個父級的遮罩,每次只顯示一張圖,其餘的都隱藏起來。對圖片新增絕對定位,通過控制left屬性,實現照片的移動。 2.圖片移動動畫原理:從a位置移動到b位置,需要先計算兩點之間的差值,通過差值和時間間隔,計算出每次移動的步

Android 實現 自動+手動滑動+指示+點選事件

1.圖片載入框架compile 'com.github.bumptech.glide:glide:3.5.2' 2.一個先寫一個佈局  <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns

android簡單實現(左右無限滑動,自動輪

直接上程式碼了,都有註釋,原理很簡單 public class MainActivity extends AppCompatActivity { private static final String Tag = MainActivity.class.getSimpleName();

Android實現

一個可以無限迴圈的輪播LoopSwitchViewScreenShotimageGIFimage實現目標可以手動左右滾動可以自動輪播自定義性強實現思路首先想到的是使用ViewPager,ViewPager本身在處理頁面左右滾動上已經很好了,在ViewPager的基礎上加上Handler讓他可以自動滾動。遇到的

js實現原理及示例(轉)

網上有很多的例子介紹,在這裡我所做的**無縫滾動**就是 通過改變元素的left值讓圖片呈現左右滾動的效果。 我們首先看一下 div+css 的結構樣式: div+css程式碼 <!DOCTYPE html> <html> <

Android 實現 一 :三方框架 自定義viewPager (CircleViewPager.)實現無限

使用流程:1  。 gradle中新增依賴compile 'com.zhpan.library:viewpager:1.0.3'2.在xml檔案中新增如下程式碼:<com.zhpan.viewpager.view.CircleViewPager andr

Android

網址 ott not 設置 amp 文件添加 .cn ive create package com.example.carson_ho.android_banner;import android.os.Bundle;import android.support.v7.app

AndroidBanner

Android實現輪播圖 昨天早睡,今天早上精力充沛!所以寫一篇部落格記錄一下。 效果圖: 第一步新增依賴: compile 'com.youth.banner:banner:1.4.9' 第二步在佈局中新增: <com.youth.banner.Banner

Android Banner切換圖片的效果

Android XBanner使用詳解 2018年03月14日 08:19:59 AND_Devil 閱讀數:910   前言:現如今的很多APP都

android AutoScrollViewPager展示網路圖片

1.匯入需要使用的包 compile 'com.github.JakeWharton:ViewPagerIndicator:2.4.1' 2.寫2個需要使用的檔案 第一個檔案 public class AutoScrollPagerFragment extends Fr

自定義開發一個android控制元件BannerImg

app開發中經常會用到輪播圖控制元件,這裡乾脆自定義開發一個常用的元件(主要使用ViewPager+ImageLoader),以後每次呼叫時,用起來方便:) 先看下效果圖: 自定義的控制元件為BannerImg類,首先看佈局檔案 bannerimg.xml <?x

androidBanner的使用及詳解

今天帶給大家一個比較實用的輪播圖框架,banner 1.匯入依賴 'com.youth.banner:banner:1.4.9' 2.新增許可權 <uses-permission android:name="android.permissi

Banner(網路介面實現

依賴 implementation 'com.youth.banner:banner:1.4.10' implementation 'com.github.bumptech.glide:glide:3.8.0' implementation 'me.imid.swipeb

android 簡單demo

github banner輪播圖框架:https://github.com/youth5201314/banner 可以設定輪播樣式、動畫、輪播和切換時間、位置、圖片載入框架等! 原來這位大神的輪播圖DEMO功能齊全,但我不需要複雜的功能,實現圖片輪播即可。 故簡化成下面圖片所示。 【and

Android 從 0 到 1

輪播圖是 Android 常用功能之一,效果大概是這樣的: 之前我封裝寫了一個,基本達到了要求,是繼承了 Fragment(當時腦袋肯定鏽掉了),裡面 Viewpager add Fragment,這次專案多處有輪播圖,發現之前封裝的不夠用,簡直漏洞百出:1、比如底部 point 的位置,