iOS開發那些事兒(一)輪播器

来源:http://www.cnblogs.com/conorBlogs/archive/2016/01/22/5124826.html
-Advertisement-
Play Games

前言 市面上絕大部分的APP被打開之後映入眼帘的都是一個美輪美奐的輪播器,所以能做出一個符合需求、高效的輪播器成為了一個程式員的必備技能。所以今天的這篇博客就來談談輪播器這個看似簡單的控制項其中蘊含的道理。正文 首先我們來分析一下該如何去實現一個類似下圖的輪播器(圖片數量、URL由伺服器返...


前言

          市面上絕大部分的APP被打開之後映入眼帘的都是一個美輪美奐的輪播器,所以能做出一個符合需求、高效的輪播器成為了一個程式員的必備技能。所以今天的這篇博客就來談談輪播器這個看似簡單的控制項其中蘊含的道理。

正文

    首先我們來分析一下該如何去實現一個類似下圖的輪播器(圖片數量、URL由伺服器返回):

    

          

     策略一:UIScrollView->UIImageView->NSTimer輪詢 這算是常規的策略,但是如果仔細想想,如果伺服器返回給你50圖片是不是就需要創建50個UIImageView來做容器。這種性能肯定不是最優的。其次所有的UIImageView是按照次序排列,腦補一下如果到最後一張圖片要重新回到第一張圖片你的話,UIScrollView會被升拉到第一個位置。效果太差!

     策略二想想UITableViewCell的重覆利用,我們也可以重覆利用其中的UIImageView。對於我們來說輪播器三個UIImageView就足夠用了,分為當前視野中的CenterImageView、前一張LeftImageView、後一張RightImageView。不同的是他們之間的圖片切換,下麵我們就嘗試去做高效的輪播器。

代碼實現

 

  1. 初始化所需控制項:

  

  2.寫一個專門控制沒次滑動結束去計算左中右三張序號並載入成對應的圖片。

/** 這裡我起名叫reloadAllImageView */

-(void)reloadAllImageView{

    CGPoint offset = _backScrollView.contentOffset;                       /** 獲取到scroll的X軸偏移量 */

 

       if (offset.x == 2 * DeviceWidth){                      /** 這裡有兩種邊界情況要處理 (1).由first—>last (2)last->first */

        /** (2) */

            _centerImageIndex        = (_centerImageIndex + 1)%3;          /** 3代表圖片的數量,這裡要主頁類型的強轉換。_centerImageIndex(NSUInteger)用於記錄當前圖片序號*/

            _pageControl.currentPage = (_pageControl.currentPage + 1)%3;

        }

        else if (offset.x == 0){

            /** (1) */

          if (_centerImageIndex == 0) {                        /** 一種特殊情況 當_centerImageIndex等於0的時候 去計算(_centerImageIndex - 1) % 3並不是我們想要的結果 */

              _centerImageIndex = 3;                          /** 嘗試了很久,計算類型轉換也就只有三張圖片會有問題。如果有興趣的朋友可以進行深入研究 */

          }                                      /** -1 % 3 = 0   如果都是有符號的結果是-1,如果按照無符號處理的話結果是0。難道計算過程應該先向前借位再進行計算? */

          _centerImageIndex        = (_centerImageIndex - 1) % 3;    

          _pageControl.currentPage = (_pageControl.currentPage - 1)%3;

        }

      _centerImageView.image         = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",_centerImageIndex + 1]];

      NSUInteger leftImageViewIndex  = (_centerImageIndex - 1)%3;

      NSUInteger  rightImageViewIndex = (_centerImageIndex + 1)%3;

      if (leftImageViewIndex == 0 && _centerImageIndex == 0) {          /** 同上暫時處理計算特殊情況 */ 

          leftImageViewIndex = 2;

      }

      _leftImageView.image           = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",leftImageViewIndex + 1]];

      _rightImageView.image          = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",rightImageViewIndex + 1]];

}
    3.現在輪播器應該可以在邊界正常切換了。現在需要再加上一個計時器來自動滑動即可:

/** 聲明一個定時器 */   /** 用weak的原因:self如果強擁有了Timer,之後你要設置計時器的Traget和選擇子selector的時候,Timer又會保留目標對象直到失效。產生保留環 */

@property(nonatomic,weak)NSTimer * timer;

/** 定時器初始化 */

   -(void)initTimer

   {

       self.timer = [NSTimer scheduledTimerWithTimeInterval:animationTime target:self selector:@selector(updateImageView:) userInfo:nil repeats:YES];

   }

  -(void)updateImageView:(NSTimer *)timer

  {

      [_backScrollView setContentOffset:CGPointMake(DeviceWidth*2, 0) animated:YES];

      [NSTimer scheduledTimerWithTimeInterval:0.4f target:self selector:@selector(scrollViewDidEndDecelerating:) userInfo:nil repeats:NO];

  }

/** 計算載入所有圖片然後移動的中間視野 */

  -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

      //重新載入圖片

      [self reloadAllImageView];

      //移動到當前視野

      [_backScrollView setContentOffset:CGPointMake(DeviceWidth, 0)];

      //設置腳標

      _pageControl.currentPage = _centerImageIndex;

  }

  4.自此輪播器大概雛形已經搞定了。剩下的就是需要搞定計時器和用戶滑動操作的互斥事件處理。

/**記錄一個bool值用於確定滑動操作的願意你。YES,計時器觸發,NO則為用戶觸發*/

     (1).計時器的觸發事件中,肯定是由計時器觸發的滑動。所以這裡bool值為YES

  (2).載入替換圖片的時候我們要進行判斷(如果是用戶觸發的時候我們要將計時器取消並從空為0)

 

    if (!bool) {

 

          [self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:animationTime]];

 

      }

 

       bool = NO;

結尾

    由此輪播器就實現了,但是其中還是有問題需要解決<1>.限制必須要三張圖片不然會crash <2>沒有封裝成單獨的scrllview以供使用。後續可能會對這些問題加以思考並重新優化。也許嘗試用UICollection來做也是個很好的想法。

            最後經過寫這篇博客也有一個目的,其實任何一個看似簡單的功能要深入挖掘的話還是有很說知識的,也發現了自身的不足。最後如果各位大神們看到了博客有任何想法意見的歡迎下麵留言。大家一起探討一起進步。謝謝各位!

 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 在文章《Android程式員從小白到大神必讀資料彙總(一)》裡面介紹了幾篇Android入門和提升效率的技術資料,今天小編收集了5篇進階的資料,趕緊來看看吧!另外,歡迎大家加入工程師博主交流群:391519124,交流博客經驗和技術一、Android開發相見恨晚的方法和介面 Android開發中,有...
  • 1.Stream 與IRandomAccessStream轉換 2.為Group創建Person的示例代碼 3.FaceIdentify 介面調用出現問題
  • 別再使用stringByAddingPercentEscapesUsingEncoding 當遇到發送網路請求的參數中有漢字的情況,很多人一股腦地使用 進行轉義,這樣帶有漢字的urlString就會將每個漢字轉成相應的unicode編碼對應的3個%形式,這叫urlEncode(每個能寫後端的語言都....
  • 最近在做項目的時候經常自定義一些輸入框,今天在這裡分享給大家。我的思路就是繼承於系統的控制項然後利用drawRect重畫裡面的控制項。那麼drawRect是怎麼工作的呢?drawRect的工作原理:首先蘋果是不推薦我們直接使用drawRect進行工作的,直接調用他也是沒有任何效果的。蘋果要求我們調用UI...
  • 一:return語句總是用在方法中,有兩個作用: 一個是返回方法指定類型的值(這個值總是確定的), 一個是結束方法的執行(僅僅一個return語句)。二:實例1 -- 返回一個Stringprivate String gets(){ String s = "qw789" ; ...
  • demo鏈接:http://pan.baidu.com/s/1pJYHfMN做用戶信息持久化最麻煩的就是沙盒存取,然後再給單例賦值,我將這些操作封裝了一下,只需要傳入KEY中包含所有屬性的字典就行了,避免了繁瑣的操作
  • Genymotion 安卓模擬器確實比安卓原生的模擬器快,但是除了快就找不到其他優點了...曾經嘗試在VM虛擬機內的Ubuntu系統裡面再運行Genymotion的,主要原因是要翻牆去下載一些東西,又不想完全連到vpn上,不過最後的結果是雙重夢境失敗,具體原因不是很清楚,提示是不能虛擬化(也許是技術...
  • 問題描述:Gradle version 2.10 is required. Current version is 2.8.Gradle版本由2.8升為2.10後,發現所有依賴play-services的module都無法構建了,提示如下錯誤:java.io.FileNotFoundException...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...