iOS開發之三個Button實現圖片無限輪播(參考手機淘寶,Swift版)

来源:http://www.cnblogs.com/ludashi/archive/2016/07/15/5659465.html
-Advertisement-
Play Games

這兩天使用Reveal工具查看"手機淘寶"App的UI層次時,發現其圖片輪播使用了三個UIButton的復用來實現的圖片迴圈無縫滾動。於是乎就有了今天這篇博客,看到“手機淘寶”這個幻燈片的UI層級時,就想要動手使用三個Button來實現一下,當然本篇博客使用是Swift語言,思路就是使用三個Butt ...


這兩天使用Reveal工具查看"手機淘寶"App的UI層次時,發現其圖片輪播使用了三個UIButton的復用來實現的圖片迴圈無縫滾動。於是乎就有了今天這篇博客,看到“手機淘寶”這個幻燈片的UI層級時,就想要動手使用三個Button來實現一下,當然本篇博客使用是Swift語言,思路就是使用三個Button進行圖片無限輪播。之前發過兩篇關於圖片輪播的博客,一個是沒有使用ImageView復用的,一個是使用兩張ImageView進行復用來實現圖片輪播的,都是使用的Objective-C實現的,併在github上進行了代碼分享。

本篇博客就是介紹如何去一步步的封裝這個三個Button的無限輪播的組件的。在實現時將該無限輪播的組件進行了封裝,需要你在實例化該組件後,傳入一個存放圖片地址的數組,數組中可以是本地圖片的名字,也可以是一個網路圖片的地址。如果是網路圖片的地址,組件中會使用NSRULSession並採用合適的緩存策略從網路載入圖片,載入完後在我們的組件上進行顯示。廢話少說,進入我們今天的主題。

今天的博客完全是個人興趣愛好,也不是公司中項目要使用的緣故才去實現的。就是看到了淘寶中的輪播圖,從UI層級上感覺這樣可以實現,於是乎就打開Xcode,創建個Swift工程實現一把,過程還是蠻愉快的。當然今天封裝組件的名稱是以公司的名稱首字母做的首碼了,這也便於在以後的工作中遇到該問題直接拿過來就用呢。

 

一、對“手機淘寶”UI層次的簡單分析

下方截圖就是當時我用Reveal工具查看的手機淘寶App的UI層級,下方只是幻燈片的部分。下方整個頁面是使用UICollectionView來實現的了,下方的幻燈片所在的UIScrollView就放在UICollectionView上的一個Cell上。當然這不是我們今天的重點,我們將目光轉移到左邊紅框中的數學層級上。可以明顯的看出UIScrollView上貼了三個UIButton,而每個UIButton上又貼了一個UIImageView

需要註意的一點是你看到UIButton是三個Button的中間一個,從下麵UI視圖中我們不難分析出,無論當前顯示的是第幾張圖片,你看到的永遠是中間Button上顯示的圖片。也就是將要顯示的圖片放到中間的Button上,左邊的Button存放上一張圖片,右邊的Button存放下一張圖片。當用戶左劃或者右劃後,我們要做的事情就是將中間按鈕放到可視區,並且設置成要顯示的圖片,當然左右兩個Button都得設置成相應的圖片,便於用戶下次移動。當然這隻是我的個人猜測,上面這種思路使用代碼來實現是完全可行的,並且可以實現無迴圈無縫滾動了。

當然,上面說的原理比較簡單,具體使用代碼實現起來還是需要許多細節的。比如用戶滑動時定時器的掛起和喚醒,用戶左右滑動方向的記錄,便於自動輪播時的方向與用戶上次滑動的方向一致,非同步載入網路請求圖片,載入後顯示在相應的Button上,通過Closure回調出用戶點擊事件可當前圖片的索引信息等等需要註意的細節。敲代碼也有幾年時間了,有一點感觸挺深的就是“說和做”完全是兩碼事,也就是你有思路和你把你的思路用代碼實現,這是完全不同的概念。當然正確的思路固然重要,但是不去實現再好的思路也是枉費,實踐出真知嗎。說這麼多,有回到了說與做的問題上,這話題就不多討論了,高執行力,高自製力好處是多多的。言歸正傳,回到今天的主題。

  

 

二、從“原理圖”中來看今天輪播的主題

下方就是今天要實現的輪播組件的原理圖,思路就是這麼個思路,要實現起來還得靠代碼往上摞呢。下方解析圖是以輪播5張圖片為例。初始化狀態是你看到的是第一張圖片,第一張圖片位於三個Button的中間,然後左邊就是最後一張圖片,右邊是第二張圖片。如果用戶想右滑動顯示的第二張圖片(對應著下方的第一步),當第二張圖片已經完全顯示出來後,我們要做的第一件事情就是將用戶移動的位置進行複位,也就是將第二個Button移動到顯示的位置,然後設置按鈕上顯示相應的圖片。第一個按鈕就顯示當前圖片的前一張圖片,如果當前顯示的是第一張圖片,那麼第一個按鈕上就顯示最後一張圖片。第三個按鈕就顯示當前圖片的下一張圖片,如果當前顯示的圖片是最後一張圖片的話,那麼第三個按鈕上就顯示第一張圖片。這樣就可以圖片輪播了。

  

 

三、該自定義控制項的視圖層級

下圖就是我們按照上面的思路,使用ScrollView上添加3個Button來實現的圖片輪播,無縫滾動的效果還是蠻OK的。在下方運行效果中美女圖片是從本地載入的,而風景圖片是使用NSURLSession和GCD的東西並行非同步的從網路獲取的,獲取完後再載入到相應Button的ImageView上。下方就是我們本篇博客相關Demo的運行效果,單從效果上來看,與之前所發佈的圖片輪播沒有什麼區別,但是其內部實現機制還是有較大區別的。接下來就逐步的看一下代碼實現。

  

上面是運行效果,下方是UI的層級。當然也是用我們強大的Reveal來查看的了,下方紅框中就是我們圖片輪播的視圖層級。該視圖層級與“手機淘寶”上是一致的,都是在UIScrollView上貼了三個Button,然後在每個Button上貼了一個ImageView。層級比較簡單,而你看到的當然是中間Button上的ImageView了,更多細節請看下圖。

  

 

四、代碼實現

運行效果看完了,UI層級結構也看完了,那麼接下來就到了我們代碼實現的時刻了。下方從組件的調用方式入手,逐步的去看一下上述效果是如何實現的。

1.上述組件的調用方式

下方代碼段就是上述組件的實例化和調用方式,首先進行初始化,然後將該組件添加到父視圖上。之後將要顯示的圖片數組imagesNameArray傳入組件中,最後設置一下組件的閉包回調即可,該回調將每個按鈕點擊的時間回調給組件的使用者,該Closure的參數是當前點擊按鈕上所顯示的Image的索引,說白了也就是你當前點擊的第幾張圖片。

  

在調用組件時,傳入給組件的參數是一個數組,下方代碼就是我們初始化imagesNameArray的函數。從該代碼段中我們不難看出,該數組中存儲的有本地圖片的名字,也有UIImage的對象,也有網路圖片的URL。將含有三種元素的數組傳給我們的組件實例,這些數組中的資源就可以按照數組中的順序依次的迴圈輪播了。

  

 

2.上述組件的核心代碼

組件調用方式還是蠻簡單的,看完調用方式,接下來來看一下具體的代碼實現。下方是我們組件中比較核心的實現部分。

(1).非同步載入網路圖片

下方代碼段就是遍歷我們的ImagesNameArray,找出該數組中所有的網路圖片的URL,每找到一個URL就開啟一個線程來請求該地址中的圖片。下方的queue是並行隊列,此處當然是並行隊列的非同步執行了。關於GCD的東西,請參考之前的博客《Grand Central Dispatch詳解》。

  

下方代碼段就是requestImage()方法中的內容了,該方法中使用NSSession並配置相應的緩存策略來請求網路圖片。載入完圖片後,將ImagesNameArray中相應的URL替換成相應的UIImage對象,然後在主線程中更新UI顯示相應的圖片,具體代碼如下所示。

  

 

(2)moveImageView()方法的實現

該方法負責將按鈕歸位與賦值,該方法對應著上述原理圖的第二和第三步。上面網路請求完一張圖片後就會調用該方法更新UI。該方法的具體實現如下所示。下方代碼中首先獲取當前顯示的頁數,也就是當前顯示的Image的索引,然後將第二個Button移動到可視區,最後調用setButtonImage()函數將每個Button上的ImageView設置成相應的Image。

  

 

(3)、定時器的實現

圖片要隔段時間自動輪播,此處我們使用的是dispatch_source中的定時器類型來實現的自動輪播。下方就是我們定時器的實現,如下所示,代碼比較簡單,在此就不做過多的贅述了,創建完定時器我們不要忘了對定時器的source進行喚醒即可。

  

當用戶進行手動切換時,我們要對定時器進行相應的掛起和喚醒操作。也就是說當用戶開始滑動時我們要對定時器進行掛起,當用戶滑動結束後要對定時器進行喚醒。當然這些都是在ScrollView相應的代理方法中進行處理的,具體如下所示:

  

 

(4)、滑動結束後更新按鈕的位置和圖片

無論是手動滑動,還是使用定時器滑動,滑動結束後我們都需要更新一下按鈕的位置和按鈕上要顯示的圖片。所以我們還需要使用到UIScrollView上的一個代理方法,那就是scrollViewDidScroll(),在該代理方法中我們調用了moveImage()方法來更新Button的位置和Button上ImageView要顯示的圖片信息。沒有這個方法,圖片就動不起來了,具體代碼如下所示:

  

 

上述是該Demo的核心代碼,更為詳細的代碼請移步於github: https://github.com/lizelu/CEImagesScrollDisplay, 因本篇博客篇幅有限,更具體的細節在此就不做過多贅述了,Demo已在上述github上進行分享。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 線上實例 實例演示 預設 實例演示 每周第一天 實例演示 輸入框插件 實例演示 HTML data 屬性 實例演示 回調函數1 實例演示 回調函數2 使用方法 複製 複製 下載 ...
  • 安卓v7支持包下的ListView替代品————RecyclerView RecyclerView這個控制項也出來很久了,相信大家也學習的差不多了,如果還沒學習的,或許我可以帶領大家體驗一把這個藝術般的控制項。 據官方介紹,該控制項是屬於之間用的非常多的ListView和GridView的替代品,既然能替 ...
  • PagerAdapter 簡介 PagerAdapter是android.support.v4包中的類,它的子類有FragmentPagerAdapter, FragmentStatePagerAdapter,這兩個adapter都是Fragment的適配器,用於實現Fragment的滑動效果,這兩 ...
  • squareup 推出 retrofit2 已經有一段時間了,現在的版本比較穩定,沒有什麼大坑了。網路上的教程要麼太簡單,只是個Demo;要麼有些落時,要麼復用性比較差,所以自己寫個教程([email protected]),供大家參考。 1. 首先在build.gradle引入依賴 註意,這裡 ...
  • App Store: 編程詞典 - Swift version 1. UI優化 2. 提升穩定性 3. 換用內容免費,功能收費形式(老用戶不受影響) App Store: 編程詞典 - Swift version ...
  • App Store: 天的故事 1. 界面優化 2. 修複bug App Store: 天的故事 ...
  • 02
    02 ...
  • 相信大家都熟悉自動識別提示吧,在我們的生活中隨處可見,今天就讓我為大家簡單介紹一下它是如何設計的。 所謂自動識別輸入即是根據用戶輸入的已有信息,為用戶提示可能的值,方便用戶完成輸入。在Android設備上這種功能分為:AutoCompleteTextView和MultiAutoCompleteTex ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...