1. 程式人生 > >iOS:狀態列提示控制元件的實現原理

iOS:狀態列提示控制元件的實現原理

現在很多流行的軟體都加入了狀態列提示的功能,比如手機qq,微信等,今天我們就一起來看看狀態列提示控制元件的原理與實現。

一、狀態列提示的實現原理

不知道大家看到狀態列提示控制元件,第一感覺它是怎麼實現的呢?

我們知道即使平時寫的view是充滿全屏的,也始終不會顯示到 statusBar的上層的。也就是說statusBar應該是一個特殊的view,始終位於程式的topLevel,這就容易聯想到UIKit中一個特 殊的view-----UIWindow。UIWindow有一個windowLevel的屬性剛好能實現一直保持在上層的功能,於是方向就比較明確了。 我較早寫的兩篇部落格

UIWindowLevel詳解以及關於UIWindow的一點兒思考中對windowLevel有過詳細的介紹和驗證。

確定了使用UIWindow來實現狀態列提示控制元件,好像問題就全部解決了,真的是這樣嗎?

如果你的程式僅僅支援portrait方向的話,那麼最主要的功能就結束了,剩下的事情就是文字框佈局和簡單動畫的實現了。但如果你的控制元件要支援其他三個方向的話,就還需要處理window的旋轉。

iOS中完整的旋轉流程如下: 裝置檢測到方向旋轉->UIApplication收到旋轉事件->通知window裝置發生了旋轉->window通知它的 rootViewController進行旋轉->viewController會調整自身view的transform。觀察發現自始至終 window本身的位置和方向是沒有發生變化的,也就是說如果自己建立一個window用於展示提示,我們需要自己處理該window的旋轉,根據不同的 方向調整window的位置和transform。

綜上要實現狀態列提示控制元件我們需要做以下兩件事:

1、建立一個UIWindow,指定它的frame為statusBar的frame,並且設定該window的windowLevel級別略高於statusBar的windowLevel。

2、註冊系統的旋轉通知,監測裝置方向變化,根據當前裝置的方向做出相應的調整。

整個過程中主要用到了UIWindow和transfrom的知識,這兩部分知識我前面寫的部落格都有涉及,難點主要集中在自己旋轉window這一塊。

二、Window的旋轉

UIKit通過UIWindow和UIViewContoller為我們提供了一套旋轉支援的框架,在方向變化以後viewController中view的座標系統就已經被轉到正確的方向了,我們只需要簡單的重新佈局就可以了。我們現在是直接通過UIWindow實現狀態列提示控制元件,因此需要自己完成對該window進行旋轉的操作。

我們知道對當前view設定的transform是針對它的父view的,window本身就是一種特殊的view。你可能會疑問window不就是最底層的view,它還有父view嗎?

答案是YES,不信的話你可以列印一下 window的superView看看。window預設方向是portrait方向,向下y座標增加,向右x座標增加。因此Portrait方向我們只 需要向普通的view那樣佈局就可以了,其它幾個方向我們就需要用到transform和設定位置來搞定了。

下面我們看一看從Portrait方向轉到landscapeRight方向的圖示:

上圖中從左到右展示瞭如何將初始位置(Portrait方向),旋轉到目標位置(landscapeRight方向)的過程。

1、原始window位置位於螢幕最上方(與statusBar的位置一樣)。

2、首先我們對這個window做順時針90°旋轉,變化後到達綠色繪製位置。

3、接著我們再修改window的center到螢幕最右邊並且上下居中,達到紅色虛線所示的位置。

4、最後對該window的bound進行設定,使該window充滿螢幕最右邊的區域。注意這個時候由於window的transform已經轉了90°,所以設定時width代表著高度,height代表這寬度。

下面是完整的處理旋轉到四個方向的程式碼:

  1. - (void)updateOrientation:(NSNotification*)noti 
  2.     UIInterfaceOrientation newOrientation = [[noti.userInfo valueForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue]; 
  3.     NSLog(@"new orientation: %d", newOrientation); 
  4.     switch (newOrientation) { 
  5.         case UIInterfaceOrientationPortrait: 
  6.         { 
  7.             self.transform = CGAffineTransformIdentity; 
  8.             self.frame = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  9.             break
  10.         } 
  11.         case UIInterfaceOrientationPortraitUpsideDown: 
  12.         { 
  13.             // 先轉矩陣,座標系統落在螢幕有右下角,朝上是y,朝左是x
  14.             self.transform = CGAffineTransformMakeRotation(M_PI); 
  15.             self.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT - HEIGHT / 2); 
  16.             self.bounds = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  17.             break
  18.         } 
  19.         case UIInterfaceOrientationLandscapeLeft: 
  20.         { 
  21.             self.transform = CGAffineTransformMakeRotation(-M_PI_2); 
  22.             // 這個時候座標軸已經轉了90°,調整x相當於調節豎向調節,y相當於橫向調節
  23.             self.center = CGPointMake(HEIGHT / 2, [UIScreen mainScreen].bounds.size.height / 2); 
  24.             self.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, HEIGHT); 
  25.             break
  26.         } 
  27.         case UIInterfaceOrientationLandscapeRight: 
  28.         { 
  29.             // 先設定transform,在設定位置和大小
  30.             self.transform = CGAffineTransformMakeRotation(M_PI_2); 
  31.             self.center = CGPointMake(SCREEN_WIDTH - HEIGHT / 2, SCREEN_HEIGHT / 2); 
  32.             self.bounds = CGRectMake(0, 0, SCREEN_HEIGHT, HEIGHT); 
  33.             break
  34.         } 
  35.         default
  36.             break
  37.     } 

三、狀態列提示控制元件原始碼

講了那麼多,說好的控制元件呢?

下面是完整的控制元件程式碼:

View Code SvStatusBarTipsWindow.h

  1. - (void)updateOrientation:(NSNotification*)noti 
  2.     UIInterfaceOrientation newOrientation = [[noti.userInfo valueForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue]; 
  3.     NSLog(@"new orientation: %d", newOrientation); 
  4.     switch (newOrientation) { 
  5.         case UIInterfaceOrientationPortrait: 
  6.         { 
  7.             self.transform = CGAffineTransformIdentity; 
  8.             self.frame = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  9.             break
  10.         } 
  11.         case UIInterfaceOrientationPortraitUpsideDown: 
  12.         { 
  13.             // 先轉矩陣,座標系統落在螢幕有右下角,朝上是y,朝左是x
  14.             self.transform = CGAffineTransformMakeRotation(M_PI); 
  15.             self.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT - HEIGHT / 2); 
  16.             self.bounds = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  17.             break
  18.         } 
  19.         case UIInterfaceOrientationLandscapeLeft: 
  20.         { 
  21.             self.transform = CGAffineTransformMakeRotation(-M_PI_2); 
  22.             // 這個時候座標軸已經轉了90°,調整x相當於調節豎向調節,y相當於橫向調節
  23.             self.center = CGPointMake(HEIGHT / 2, [UIScreen mainScreen].bounds.size.height / 2); 
  24.             self.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, HEIGHT); 
  25.             break
  26.         } 
  27.         case UIInterfaceOrientationLandscapeRight: 
  28.         { 
  29.             // 先設定transform,在設定位置和大小
  30.             self.transform = CGAffineTransformMakeRotation(M_PI_2); 
  31.             self.center = CGPointMake(SCREEN_WIDTH - HEIGHT / 2, SCREEN_HEIGHT / 2); 
  32.             self.bounds = CGRectMake(0, 0, SCREEN_HEIGHT, HEIGHT); 
  33.             break
  34.         } 
  35.         default
  36.             break
  37.     } 
  38. 複製程式碼 
  39. 三、狀態列提示控制元件原始碼 
  40. 講了那麼多,說好的控制元件呢? 
  41. 下面是完整的控制元件程式碼: 
  42. 複製程式碼 
  43. //
  44. //  SvStatusBarTipsWindow.h
  45. //  SvStatusBarTips
  46. //
  47. //  Created by  maple on 4/21/13.
  48. //  Copyright (c) 2013 maple. All rights reserved.
  49. //
  50. #import <UIKit/UIKit.h>
  51. @interface SvStatusBarTipsWindow : UIWindow 
  52. /* 
  53.  * @brief get the singleton tips window 
  54.  */
  55. + (SvStatusBarTipsWindow*)shareTipsWindow; 
  56. /* 
  57.  * @brief show tips message on statusBar 
  58.  */
  59. - (void)showTips:(NSString*)tips; 
  60. /* 
  61.  * @brief show tips message on statusBar 
  62.  */
  63. - (void)showTips:(NSString*)tips hideAfterDelay:(NSInteger)seconds; 
  64. /* 
  65.  * @brief show tips icon and message on statusBar 
  66.  */
  67. - (void)showTipsWithImage:(UIImage*)tipsIcon message:(NSString*)message; 
  68. /* 
  69.  * @brief show tips icon and message on statusBar 
  70.  */
  71. - (void)showTipsWithImage:(UIImage*)tipsIcon message:(NSString*)message hideAfterDelay:(NSInteger)seconds; 
  72. /* 
  73.  * @brief hide tips window 
  74.  */
  75. - (void)hideTips; 
  76. @end 

SvStatusBarTipsWindow.m

  1. //
  2. //  SvStatusBarTipsWindow.m
  3. //  SvStatusBarTips
  4. //
  5. //  Created by  maple on 4/21/13.
  6. //  Copyright (c) 2013 maple. All rights reserved.
  7. //
  8. #import "SvStatusBarTipsWindow.h"
  9. #define SCREEN_WIDTH  ([UIScreen mainScreen].bounds.size.width)
  10. #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
  11. 相關推薦

    iOS狀態提示控制元件實現原理

    現在很多流行的軟體都加入了狀態列提示的功能,比如手機qq,微信等,今天我們就一起來看看狀態列提示控制元件的原理與實現。 一、狀態列提示的實現原理 不知道大家看到狀態列提示控制元件,第一感覺它是怎麼實現的呢? 我們知道即使平時寫的view是充滿

    iOS開發UI基礎—29UIScrollView控制元件實現圖片輪播

    一、實現效果 實現圖片的自動輪播            二、實現程式碼 storyboard中佈局 程式碼: 1 #import "YYViewController.h" 2 3 @interface YYViewController () <UIScrollViewDelegat

    iOS之OC使用原生控制元件實現分享到QQ、微信、簡訊、微博等的兩種方法

    現在任何一款APP都離不開“分享”,產品設計可能是覺得有分享能更好的推廣自己的產品吧。。。 一種是使用UIActivityViewController, 另外一種是使用Social框架中的SLComposeViewController 一、UIActivityViewCon

    下拉重新整理、上拉載入更多控制元件實現原理及解析(一)

    以前那個賬號,以後可能不用了,把文章搬過來!!! 效果預覽 接受hi大頭鬼hi的建議,來一個動態圖,方便大家知道這是個什麼東西。 動機 原理     無論是下拉重新整理還是上拉載入更多,原理都是在內容View(ListView、Re

    iOS開發常用的UIView控制元件——UILabel、UITextField、UIButton

    前面幾篇文章已經對iOS開發中比較基本的幾個檔案進行了瞭解,今天主要學習StoryBoard檔案和幾個常見的UI控制元件。 Storyboard功能是在iOS5開始新增的功能,一種新技術的出現大多是為了彌補舊技術的不足,而在storyboard之前iOS 開發設計介面是使用nib檔案(xib

    IOS開發學習筆記十六 使用UITableView控制元件實現微博列表效果

    效果:專案地址 微博列表唯一需要注意的是每個條目的列表行高不一致,需要在UITableView的代理方法heightForRowAtIndexPath中動態設定行高 需要建立Module物件CZMicroBlogFrame來儲存UITableCell的子View的

    IOS開發學習筆記十四 UITableView控制元件實現ListView的效果

    效果圖:專案地址 ViewController對應的程式碼: #import "ViewController.h" #import "CZHero.h" @interface ViewController () <UITableViewDataSource, UIT

    IOS開發學習筆記十三 UIScrollView控制元件實現輪播圖

    效果圖:專案地址 程式碼: #import "ViewController.h" @interface ViewController ()<UIScrollViewDelegate> @property (weak, nonatomic) IBOutlet

    如何用 DataGrid 控制元件實現驗證

    利用 DataGrid 控制元件,您既可以在單元格級別也可以在行級別執行驗證。 通過單元格級別驗證,將可在使用者更新值時驗證繫結資料物件的個別屬性。 通過行級別驗證,將可在使用者提交對行的更改時驗證整個資料物件。 您也可以為驗證錯誤提供自定義的可視反饋,或使用 DataG

    【轉】WPF自定義控制元件與樣式(11)-等待/忙/正在載入狀態-控制元件實現

    一.前言   申明:WPF自定義控制元件與樣式是一個系列文章,前後是有些關聯的,但大多是按照由簡到繁的順序逐步釋出的等。   本文主要有三種實現方式: 簡單忙碌狀態控制元件BusyBox; Win8/win10效果忙碌狀態控制元件ProgressRing; 彈出非同步等待框WaitingB

    使用CToolTipCtrl控制元件實現游標移動到一個控制元件時顯示特定的提示資訊

    在利用MFC程式設計時,通常要需要知道某些控制元件代表一些資訊,或在文字框輸入時,需要知道文字框輸入內容提示資訊,ToolTip是Win32中一個通用控制元件,MFC中為其生成了一個類CToolTipCtrl,可實現提示資訊顯示。過程如下: 1、新增CTool

    Android進階之自定義View實戰(一)仿iOS UISwitch控制元件實現

    一.引言 個人覺得,自定義View一直是Android開發最變換莫測、最難掌握、最具吸引力的地方。因為它涉及到的知識點比較多,想在實際應用中駕輕就熟,由淺入深,你需要掌握以下知識點: 1. View的繪製機制以及Canvas、Paint、Rect等的常用方

    Android 實現IOS上的水滴效果控制元件

    看到ios版上QQ重新整理效果像水滴,然後自己也想著去實現這樣的效果,這篇文章暫時沒有介紹下拉重新整理的效果,只是單獨用一個控制元件來實現這樣的水滴效果。 效果圖如下: 一、總體思路 1、畫兩個圓形,其中一個就是上面的大圓,還有一個是下面的小圓,大

    iOS設定狀態樣式,顯示控制,statusBarStyle, statusBar

    滿滿的乾貨 1、在不同的應用中,有關狀態列的樣式是不定的,系統的預設樣式是黑色的,然而有一些應用是需要白色的,所以就需要進行相關的設定,設定狀態列的樣式有2種方式,下面分別講述一下。  2、方法一: 直接在需要改變預設狀態列樣式的控制器中實現一個方法(其他任何事情都不

    經驗及技巧用MediaElement 控制元件實現全屏並自動旋轉至橫屏!

    如何實現搜狐視訊開始一部分螢幕播放,點選後實現全屏並自動橫屏。我剛開始思路是自己控制進行旋轉,不過最後還是有些問題。其實不用那麼麻煩,方法很簡單。只要設定MediaElement的AreTransportControlsEnabled 屬性均為true即可。AreTrans

    安卓自定義控制元件-實現IOS版UC瀏覽器三點載入動畫效果

    1.實現分析 廢話不多說,看下IOS版UC瀏覽器的載入效果 簡單畫個圖看下整個過程 1.B圓的圓心移動的座標為:A圓和B圓的圓心的距離L的中點為圓心O1的下半圓的運動軌跡經過的座標,就有一個由B位置到A位置圓周運動的軌跡。 2.C圓的圓心

    iOS使用NSMutableSet記錄cell控制元件選中狀態避免cell重用問題

    我在tableView上面有個button,當我選中button的時候,上滑頁面發現選中的狀態沒有了,但是數組裡面新增的button tag值還在(類似於購物車那種方式)很是蛋疼,幸虧還有NSMutableSet來拯救我們啊 哈哈 廢話不多說,直接看程式碼 1

    組裝原有控制元件實現橫向滾動的時間選擇器,可滑動 點選,初始狀態在指定位置

    簡介 前段時間,產品設計了一個橫向的滾動的時間選擇器,由於工作很急,也沒時間來自定義view,而且目前開發的專案很老了,不支援V7的包,所以我不能用recyclerview。我就將就之前的GridView和HorizontalScrollView,組裝了一哈就可以了。本

    專案實戰流水線影象顯示控制元件重新整理、1ms一次、縮放、拽拖、拽拖預覽、效能優化、支援OpenGL GPU加速)

      需求   流水線影象掃描採集控制元件(帶模擬資料測試)效能需求  1.需至少滿足可1ms接收一次列資料,而不丟包(接收後可不必立馬顯示)  2.圖片重新整理率可達30HZ;限制需求  1.圖片高度最小隻能縮小為控制元件在介面顯的高度  2.控制元件在介面顯示的大小可任意調整,圖片可自適應控

    webbrowser 控制元件實現WinForm與WebForm互動

     WebBrowser 控制元件可以讓你裝載Windows Form 應用程式中的 Web 網頁和其它採用瀏覽器的檔案。可以使用webbrowser 控制元件將現有的web框架控制項加入至 Windows Form 客戶端應用程式。還是直接看程式碼吧。 WebBrowser 控制項