1. 程式人生 > >viewpager輪播圖的實現(簡潔易懂)

viewpager輪播圖的實現(簡潔易懂)

在做這個效果的時候,我第一時間看了網上的輪播方式,發現問題很多,有的人在程式碼裡大量的判斷手動滑動和自動滑動的狀態改變,有的人的輪播是定義了一個很大的Int值,通過順序播放相同的圖片來實現的偽輪播,看過這些程式碼感覺並不滿意,所以嘗試自己實現。

在輪播更新UI的時候,我嘗試了Thread+handler,handler.postdelay,和timer+timertask+handler的方式,前兩種方式都會出現一些小Bug,並且不利於功能擴充套件,讀者可自行嘗試,所以我採用了第三種方式。

在解決手動滑動和自動滑動的上,其實根本不用設定什麼標誌位進行大量的判斷,這是一個思維誤區,因為我們根本不需要解決這兩者之間的衝突,我們只需要關注當前頁面是不是改變成功了,當前頁面是第幾個就可以了。所以我們只需要判斷onPageScrollStateChanged的state為2的時候,這個頁面的position就可以解決上述問題。

如果要給自己的輪播增加一些文字描述也非常的簡單,具體可以看我下面的程式碼分析。

效果圖:
輪播圖
直接看核心程式碼:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Context ctx;

    //viewpager初始化
    private ViewPager viewPager;
    private List<View> list;
    private LPagerAdapter adapter;

    //輪播控制
    private
Handler handler; private Timer timer; private TimerTask task; private int mPosition; //輪播內容 private LinearLayout point_container; private ImageView[] imgs; private List<ImageTip> tips; private TextView tip1; private TextView tip2; @Override protected
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); tip1 = (TextView) findViewById(R.id.tv_tip1); tip2 = (TextView) findViewById(R.id.tv_tip2); ctx = this; initdata(); initpoint(); initTip(); //自定義adapter adapter = new LPagerAdapter(ctx, list, new LPagerImgClickListener() { @Override public void ImgClick(int position) { Toast.makeText(ctx, "點選了" + mPosition, Toast.LENGTH_SHORT).show(); Intent intent = new Intent(ctx, SecondActivity.class); intent.putExtra("position", position); startActivity(intent); } }); //第一種動畫 // viewPager.setPageTransformer(true, new ZoomOutPageTransformer()); //第二種動畫 viewPager.setPageTransformer(true,new DepthPageTransformer()); viewPager.setAdapter(adapter); //監聽頁面的改變 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // Log.i("LHD", "onPageScrolled" + " positionOffset:" + positionOffset + " positionOffsetPixels:" + positionOffsetPixels); } @Override public void onPageSelected(final int position) { // Log.i("LHD", "onPageSelected" + position); } @Override public void onPageScrollStateChanged(int state) { // Log.i("LHD", "onPageScrollStateChanged:" + state); if (state == 2) {//圖片切換成功的狀態為2 mPosition = viewPager.getCurrentItem(); Log.i("LHD", "當前頁是:" + mPosition); for (int i = 0; i < list.size(); i++) { //設定所有原點 imgs[i].setImageResource(R.drawable.point1); } //設定當前頁的小圓點圖片和文字資訊 imgs[mPosition].setImageResource(R.drawable.point2); tip1.setText(tips.get(mPosition).getTip1()); tip2.setText(tips.get(mPosition).getTip2()); } } }); imgPlay(); } private void imgPlay() { //迴圈播放 task = new TimerTask() { @Override public void run() { Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } }; timer = new Timer(); timer.schedule(task, 3000, 3000); handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { if (mPosition == (list.size() - 1)) { viewPager.setCurrentItem(0, true); } else { Log.i("LHD", "bbbb: " + mPosition + "當前的程序ID: " + Thread.currentThread().getId()); viewPager.setCurrentItem(mPosition + 1, true); Log.i("LHD", "cccc: " + mPosition); } } } }; } private void imgStop() { handler.removeMessages(1); timer.cancel(); task.cancel(); } private void initdata() { list = new ArrayList<View>(); ImageView iv = new ImageView(ctx); ImageView iv2 = new ImageView(ctx); ImageView iv3 = new ImageView(ctx); ImageView iv4 = new ImageView(ctx); ImageView iv5 = new ImageView(ctx); ImageView iv6 = new ImageView(ctx); iv.setImageResource(R.drawable.image3); iv2.setImageResource(R.drawable.image4); iv3.setImageResource(R.drawable.image5); iv4.setImageResource(R.drawable.image6); iv5.setImageResource(R.drawable.image7); iv6.setImageResource(R.drawable.image8); list.add(iv); list.add(iv2); list.add(iv3); list.add(iv4); list.add(iv5); list.add(iv6); imgs = new ImageView[list.size()]; } private void initpoint() { point_container = (LinearLayout) findViewById(R.id.point_container); for (int i = 0; i < list.size(); i++) { ImageView imageView = new ImageView(ctx); imageView.setImageResource(R.drawable.point1); //對佈局控制元件新增相對屬性 LinearLayout.LayoutParams param = new LinearLayout.LayoutParams( 20, 20); //新增規則,示例 靠父控制元件最右邊 param.setMargins(10, 0, 0, 0); Log.i("LHD", "新增小圓點:" + list.size()); imgs[i] = imageView;//新增到圖片陣列 point_container.addView(imageView, param); imgs[0].setImageResource(R.drawable.point2); } } private void initTip() { tips = new ArrayList<ImageTip>(); tips.add(new ImageTip("山治:我要尋找all bule", "2016/6/23")); tips.add(new ImageTip("弗蘭奇:我要飛上天", "2016/6/24")); tips.add(new ImageTip("烏索普:我要成為勇敢的海上戰士", "2016/6/25")); tips.add(new ImageTip("羅賓:我要尋找歷史原文", "2016/6/26")); tips.add(new ImageTip("娜美:我要環繞世界一週", "2016/6/27")); tips.add(new ImageTip("路飛:我要成為海賊王!", "2016/6/28")); tip1.setText(tips.get(0).getTip1()); tip2.setText(tips.get(0).getTip2()); } @Override protected void onPause() { super.onPause(); Log.i("LHD", "onPause"); //儲存當前頁位置 mPosition = viewPager.getCurrentItem(); //停止輪播 imgStop(); } @Override protected void onRestart() { super.onRestart(); Log.i("LHD", "onRestart"); //重新啟動輪播 imgPlay(); } }

分析:

imgPlay()
這個函式就是用來控制圖片輪播的函式,
在這個函式裡,使用了Timer+TimerTask+handler的方式來更新UI。
imgStop()
這個函式用來取消圖片輪播,當按下HOME鍵或者返回鍵的時候需要將動畫取消,再次啟動Activity的時候再恢復。
initdata()
將需要輪播的圖片存放在一個List裡,並且定義了一個存放圖片的陣列。
initpoint()
根據圖片數量來新增小圓點
initTip()
圖片下面文字的初始化
重寫了onPause方法和onRestart方法,在onPause方法裡儲存圖片位置,停止動畫,在onRestart方法裡重啟動畫。

接下來看ViewPager的介面卡:
LPagerAdapter.java

/**
 * Created by LHD on 2016/6/29.
 */
public class LPagerAdapter extends PagerAdapter {

    private Context ctx;
    private List<View> mlist;
    private LPagerImgClickListener mlistener;

    public LPagerAdapter(Context ctx, List<View> mlist, LPagerImgClickListener listener) {
        this.ctx = ctx;
        this.mlist = mlist;
        this.mlistener = listener;
    }

    @Override
    public int getCount() {
        return mlist.size();
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        container.addView(mlist.get(position));
        mlist.get(position).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                Toast.makeText(ctx, "點選了" + position, Toast.LENGTH_SHORT).show();
                if (mlistener != null) {
                    mlistener.ImgClick(position);
                }
            }
        });
        return mlist.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mlist.get(position));
    }
}

和普通的viewpager介面卡沒有區別,只是增加了一個監聽,當點選圖片的時候,呼叫mlistener.ImgClick(position);

介面:
LPagerImgClickListener.java

public interface LPagerImgClickListener {
    public void ImgClick(int position);
}

另外提供了兩種viewpager的動畫,這兩種動畫都是谷歌官方提供,可以根據需要修改裡面的引數。

動畫1:
DepthPageTransformer.java

/**
 * Created by LHD on 2016/6/30.
 */
public class DepthPageTransformer implements ViewPager.PageTransformer{
    private static float MIN_SCALE = 0.75f;

    @SuppressLint("NewApi")
    @Override
    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);
        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when
            // moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);
        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);
            // Counteract the default slide transition
            view.setTranslationX(pageWidth * -position);
            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE + (1 - MIN_SCALE)
                    * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);

        }
    }
}

動畫2:
ZoomOutPageTransformer.java

package com.example.eventbus.imagecarousellhd;

import android.support.v4.view.ViewPager;
import android.view.View;

/**
 * Created by LHD on 2016/6/30.
 */
public class ZoomOutPageTransformer implements ViewPager.PageTransformer{
    private static float MIN_SCALE = 0.85f;

    private static float MIN_ALPHA = 0.5f;

    @Override
    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);
        } else if (position <= 1) { // [-1,1]
            // Modify the default slide transition to
            // shrink the page as well
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }
            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
                    / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

相關推薦

viewpager實現簡潔易懂

在做這個效果的時候,我第一時間看了網上的輪播方式,發現問題很多,有的人在程式碼裡大量的判斷手動滑動和自動滑動的狀態改變,有的人的輪播是定義了一個很大的Int值,通過順序播放相同的圖片來實現的偽輪播,看過這些程式碼感覺並不滿意,所以嘗試自己實現。 在輪播更新UI

圖片實現html js

1.簡單實現 1)實現思想:通過輪播次數來決定顯示那一張首先,可以用簡單的div 包含img的框架來實現,我們為他新增按鈕,每個按鈕對應不同的圖片,那麼,每點選一次,將要顯示的圖片的style.dispay屬性設定為'block'將不顯示的圖片的display設定為none,可以實現簡單的按

ViewPager:自動無限,手指長按停止,實現點選事件實用版

此Demo是自定義的viewpager,實現功能如下:無限自動輪播,pager點選事件處理,手指長按停止自動輪播,手指擡起恢復自動輪播; 幾乎可以滿足目前專案中的要求;大家可以直接使用; 整個Demo分兩大類,一個是自定義的ViewPager,一個是MainActivi

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

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

ViewPager Banner方式實現

1.提取的基類 package com.example.viewpager_demo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app

ViewPager Handler方式實現

1.提取的基類BaseActivity package com.example.viewpager_demo; import android.os.Bundle; import android.support.annotation.Nullable; import android.su

Android 實現效果 底部圓點狀態改變

自動輪播和手動輪播之後應該實現圓點的切換 自定義改變圓點狀態的監聽器 新建介面public interface DotChangeListener,新增方法void dotChangeListener(int index);並在ImageBannerFramLayout實

微信小程式學習筆記----初識小程式程式碼、實現

從這一節開始我們就開始接觸小程式前臺程式碼了,其實前臺邏輯還是比較簡單的,學習難度比學習一個前端框架難不了多少,記得以前一開始學前端框架的時候,流程就是:熟悉一下--檢視元件--找到要用的--複製貼上,其實對於大部分人來說,小程式前臺也是一樣。 首先,我們可以先看下小程式的

TabLayout + ViewPager 雙層巢狀,側拉展示條目頭像加listview,點選頭像可切換PullToRefreshListView重新整理載入

模組簡介: 1.底部:TabLayout + ViewPager輪播圖 2.主頁面可測拉 展示頭像,可選擇系統相簿,切換圖片(二級取樣) 3.TabLayout + ViewPager巢狀TabLayout + ViewPager以展示 正在上映 和 *

Bootstrap實現基於carousel.js框架的效果無過渡動畫

宣告式觸發需要使用到的幾個data-*屬性 1.data-ride:作用在最外層容器上,固定值:carousel 2.data-target:作用在class=carousel-indicator

Boostrap部落格網站搭建-首頁實現

1、使用輪播圖外掛這裡我們使用swiper.js外掛並附上下載地址:https://pan.baidu.com/s/1c3MifM4   下面就需要新增HTML程式碼了 <div class="jumbotron container-slider"> &

JQuery 基礎案例3—— jQuery實現無縫無回滾滾動切換效果

輪播圖無縫滾動切換原理 基本框架 <div class="slide"> <!-- 導航點 --> <ul class="slide-nav"> <li class="activ

js原生實現效果面向對象編程

alt 狀態 off wid 編程) .proto eat doc 持續時間 面向對象編程js原生實現輪播圖效果 1.先看效果圖 2.需要實現的功能: 自動輪播 點擊左右箭頭按鈕無縫輪播 點擊數字按鈕切換圖片 分析:如何實現無縫輪播? 在一個固定大小的相框裏有一個ul

原生js實現

索引 獲取 mouseout abs length ati point css ack 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta chars

vue報錯 Uncaught RangeError: Maximum call stack size exceeded 附完整實現程式碼

Vue初學者,寫專案實現輪播圖時報錯且頁面初始化後不會自動輪播。 設定的計時器時長是6000,但報錯是幾乎沒有停歇的報錯。 檢查核心程式碼,發現 錯誤一:這裡導致輪播圖初始化不輪播 mounted的方法寫在了methods裡面,將mounted的方法挪出,解決頁面初始化輪播圖不

ViewPager

.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

JS原生實現

作為一個PHP全棧攻城獅,不僅要會後端PHP和資料庫,還要會前端JS。今天原始碼時代 PHP培訓 學科老師要和大家分享一下JS原生編寫輪播圖的外掛。 說起輪播圖,很多人會選擇使用各種外掛,比如基於JQuery或其它框架的。不瞞大家,我也用過,甚至還用過Flash的輪播圖。總體來說,用起來是比較簡

移動端實現

1:HTML樣式<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-s

最簡單的實現

需求:每隔2秒切換一張圖片的效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>輪播圖</title>

側拉+TabLayout切換fragment+Viewpager小圓點和圖片上顯示標題+多條目+上拉載入+下拉重新整理

1.MainActivity主頁面 package com.example.zonghelianxi01; import android.annotation.SuppressLint; import android.support.annotation.Nullable; impor