使用appearance proxy定製控制項的預設面板(詳解)

來源:互聯網
上載者:User

標籤:

 

控制項的外觀,受到tint color,background image, background color等屬性的共同影響,通常要修改某個控制項對象的外觀,就去調用上面屬性的相關setter方法(或者其他可以修改它們的方法)就可以了。但是,如果希望整個app中的控制項都保持一致的風格,比如所有button的風格(指的是大小,背景圖,形狀等)都一樣,那麼一個一個去重複設定每個button的風格,就顯得太麻煩了。如果可以給Button類設定一個預設面板,就方便多了。appearance proxy就可以實現。

對於導覽列,tabBarController等等管理多個視圖控制器的控制項,要對它們的全域外觀進行修改,通常比較便捷的方法也是定製預設面板,也就是使用appearance proxy。下面就來詳細介紹appearance proxy。

一、首先,要瞭解一個概念appearance proxy外觀代理:

外觀代理,它是一個管理可視化類(比如控制項)的預設面板的對象。我們可以通過這個類的外觀代理,來修改這個類的預設面板(與外觀有關的屬性的預設值),或者這個類在某種場合下的預設面板。

二、需要遵守兩個協議

一個類要能夠使用外觀代理,需要遵守兩個協議,一個是UIAppearance,一個是UIAppearanceContainer協議。

1. UIAppearance協議

該協議定義了4個方法,用於擷取類的外觀代理,分別對應4種外觀代理。

2. UIAppearanceContainer協議

該協議定義了一個常量UI_APPEARANCE_SELECTOR,用來標識外觀代理可以調用的方法。既然外觀代理是用來管理類的預設面板的,那麼能夠被它調用的方法,或者說它需要調用的方法,往往就是類的某個外觀特徵的setter和getter方法。也就是說,為一個方法設定UI_APPEARANCE_SELECTOR標籤,就表示這個方法可以為外觀代理所用。當然,方法的格式是有規定的,基本格式和一般屬性的setter和getter方法格式一樣,在這個基礎上可以增加更多的參數。參數的類型只能是NSInteger或NSUInteger,否則會報錯。

三、外觀代理的工作時間官網上簡潔的表述:

所有通過外觀代理對預設面板進行的修改,只會在view layout time 時生效。在此之後,仍可以通過對象的屬性和方法來覆蓋此預設面板。

我的詳細解釋:

我們可以隨時讓外觀代理修改預設面板,準確的理解是讓外觀代理記錄好我們對預設面板的定製要求。但是外觀代理只會在view layout time時工作一次,也就是讓預設面板生效。在此之後,調用外觀代理來修改預設面板,是不會即時生效的,換言之,必須要等到下次view layout time的時候才會讓這個新定製的預設面板生效。什麼時候是view layout time?從啟動並執行效果來看,我暫且理解為載入window(或從其他window返回到本window)的時候,如果有更準確的理解,望賜教。

預設面板對類的所有的對象起作用(所謂預設,就是這個意思)。如果要在預設面板的基礎上對某個對象的外觀進行修改,就和平常一樣,調用這個對象有關外觀設定的方法即可。

四、外觀代理的擷取及使用

下面詳細瞭解UIAppearance協議中定義的4種擷取外觀代理的方法,及其對應的4種外觀代理:

1.全域外觀代理

功能:代理中的Big Boss,它可以管理控制項在任何情況下的預設面板。 
擷取代理的方法:+ ( instancetype )appearance 
比如:要擷取UINavigationBar的全域外觀代理: 
UINavigation *appearanceProxy=[UINavigation appearance];

2.只負責指定場合的外觀的外觀代理

功能:管理控制項被包含在指定的類(及其子類)中時的預設面板;管理控制項被包含在指定的視圖層級關係中時的預設面板。 
擷取代理的方法:

+ ( instancetype )appearanceWhenContainedIn:(Class<UIAppearanceContainer>)ContainerClass, …     
  • 1

解釋: 
這個方法的參數指定了某個類或者多個類。參數個數不定,最後一個參數必須是nil。 
例子: 
比如,擷取 作用於“放在UIToolbar類中的UIBarButtonItem對象”的外觀代理,這樣寫:

[UIBarButtonItem appearanceWhenContainedIn: [UIToolbar class],nil];
  • 1

注意: 
此時除了放在UIToolbar類中的UIBarButtonItem對象會受這個外觀代理管理以外,放在UIToolbar的子類中的UIBarButtonItem對象也會受這個代理管理。 
如果要指定層級關係,則傳入一個層級關係的對象。

上面說的方法從iOS 5.0開始啟用,到iOS 9.0丟棄,iOS 9.0及以後用下面的方法替代:

+(instancetype)appearanceWhenContainedInInstancesOfClasses:(NSArray<Class <UIAppearanceContainer>> *)containerTypes
  • 1

比如,設定導覽列被放在UISplitViewController或者UITabBarController裡面時的預設BarTintColor:

[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:  @[[UISplitViewController class], [UITabBarController class]]] setBarTintColor:myColor];
  • 1
3.只負責控制項在某種系統內容下的外觀的外觀代理

功能:管理類在某種系統內容下(比如橫屏、豎屏等)的預設面板。系統內容由UITraitCollection對象來指定。(查看UITraitCollection Class Reference) 
擷取代理的方法:

+ (instancetype)appearanceForTraitCollection:(UITraitCollection *)trait
  • 1
4.只負責控制項在某種系統內容、某種場合下的外觀的外觀代理

功能:管理控制項在某種系統內容、某種場合下的預設面板 
擷取代理的方法:

+ (instancetype)appearanceForTraitCollection:(UITraitCollection *)trait  whenContainedIn:(Class<UIAppearanceContainer>)ContainerClass
  • 1

以上方法從5.0開始啟用,在iOS 9.0被丟棄,iOS 9.0及以後用下面這個方法替代:

+ (instancetype)appearanceForTraitCollection:(UITraitCollection *)trait whenContainedInInstancesOfClasses:(NSArray<Class <UIAppearanceContainer>> *)containerTypes

使用appearance proxy定製控制項的預設面板(詳解)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.