en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

10.18.2012

使用 Appearance 方法自訂你的介面

   

以往我們想要重新自定 iOS SDK 內既有的物件外觀時不是要動到非正規的方法,就是要重新製作一個新的物件好讓它看起來向既有的物件般非常麻煩,不過現在只要透過 iOS 5 SDK 提供的 Appearance Proxy 做幾個簡單的設定,就可以非常輕鬆的為你的物件自訂新的外觀。

Appearance 是在 UIView 下的一個方法,這意味著所有繼承 UIView 的類別都會包含此方法,像是 UIControl、UISwitch 或是 UISlider 等等,下面程式碼就演示一些常用的物件透過 Appearance 方法來自訂新的外觀,其程式碼如下。

改變 UINavigationBar 的外觀
//設定UINavigationBar的背景圖片
UIImage *navigationBar = [UIImage imageNamed:@"UINavigationBar"];
[[UINavigationBar appearance] setBackgroundImage:navigationBar forBarMetrics:UIBarMetricsDefault];

//改變UINavigationBar的Title字形
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [UIColor whiteColor], UITextAttributeTextColor,
                                   [UIColor darkTextColor], UITextAttributeTextShadowColor,
                                   [NSValue valueWithUIOffset:UIOffsetMake(1, -2)], UITextAttributeTextShadowOffset,
                                   [UIFont fontWithName:@"Bradley Hand" size:0.0], UITextAttributeFont,
                               nil];
[[UINavigationBar appearance] setTitleTextAttributes:textAttributes];


改變 UIBarButtonItem 的外觀
//設定UIBarButtonItem的背景圖片
UIImage *UIBarButtonItem = [UIImage imageNamed:@"UIBarButtonItem"];
[[UIBarButtonItem appearance] setBackgroundImage:barButtonItem forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];


改變 UITabBar 的外觀
//設定UITabBar的背景圖片
UIImage *tabBar = [UIImage imageNamed:@"UITabBar"];
[[UITabBar appearance] setBackgroundImage:tabBar];

//設定UITabBar在被選擇到時的圖片
UIImage *selectionIndicator = [UIImage imageNamed:@"SelectionIndicator"];
[[UITabBar appearance] setSelectionIndicatorImage:selectionIndicator];


改變 UISlider 的外觀
//設定UISlider調鈕的圖片
UIImage *thumbImage = [UIImage imageNamed:@"Thumb"];
[[UISlider appearance] setThumbImage:thumbImage forState:UIControlStateNormal];

//設定UISlider調鈕左邊的影像
UIImage *minimumTrack = [UIImage imageNamed:@"minimumTrack"];
[[UISlider appearance] setMinimumTrackImage:minimumTrack forState:UIControlStateNormal];

關於 UISlider 這邊要補充說明一下,UISlider 設定可以分成三部份,調整鈕本身的圖片,調整鈕左邊到最小值這段的圖片,以及調整鈕到最大值這段的圖片,撥動調整鈕時在視覺上感覺好像有什麼東西填滿 UISlider,但其實只是這兩段影像彼此以調整鈕為準相互做橫福的放大縮小而以,而在本示範中並位對調整鈕到最大值這段的圖片做設定,直接採用預設值。


改變 UISwitch 的外觀
//設定UISwitch開啓狀態的顏色
[[UISwitch appearance] setOnTintColor:[UIColor orangeColor]];

在 iOS 6.0 SDK 中,你也可以透過另一個簡單的方式來修改 UISwitch 各部分的外觀,像是 ON / OFF 狀態的背景圖案、按鈕和背景的顏色等。
//設定整個UISwitch的顏色
[[UISwitch appearance] setTintColor: [UIColor colorWithRed:0.933 green:0.643 blue:0.307 alpha:1.000]];

設定整個 UISwitch 顏色的結果 
//設定UISwitch按鈕部分的顏色
[[UISwitch appearance] setThumbTintColor:[UIColor colorWithRed:0.469 green:0.728 blue:1.000 alpha:1.000]];

設定 UISwitch 在按鈕部分顏色的結果
//設定UISwitch開關狀態的背景
[[UISwitch appearance] setOnImage:[UIImage imageNamed:@"ON_OFF.png"]];
[[UISwitch appearance] setOffImage:[UIImage imageNamed:@"ON_OFF.png"]];

設定 UISwitch 背景顏色的結果


改變 UIStepper 的外觀
//設定UIStepper按鈕部分的顏色
[[UIStepper appearance] setTintColor:[UIColor orangeColor]];

在 iOS 6.0 SDK 中,你也可以透過另一個簡單的方式來修改 UIStepper 各部分的外觀,像是按鈕在不同狀態下的圖案背景等。
//設定UIStepper按鈕正常的顯示樣式"
[[UIStepper appearance] setIncrementImage:[UIImage imageNamed:@"Normal.png"] forState:UIControlStateNormal];
[[UIStepper appearance] setDecrementImage:[UIImage imageNamed:@"Normal.png"] forState:UIControlStateNormal];

//設定UIStepper按鈕被選取下的顯示樣式"
[[UIStepper appearance] setIncrementImage:[UIImage imageNamed:@"Highlighted.png"] forState:UIControlStateHighlighted];
[[UIStepper appearance] setDecrementImage:[UIImage imageNamed:@"Highlighted.png"] forState:UIControlStateHighlighted];

//設定UIStepper按鈕未啟用下的顯示樣式"
[[UIStepper appearance] setIncrementImage:[UIImage imageNamed:@"Disabled.png"] forState:UIControlStateDisabled];
[[UIStepper appearance] setDecrementImage:[UIImage imageNamed:@"Disabled.png"] forState:UIControlStateDisabled];


改變 UISegmentedControl 的外觀
//設定UISegmentedControl在一頒狀態下的背景影像
UIImage *segmentedControl = [UIImage imageNamed:@"UISegmentedControl"];
[[UISegmentedControl appearance] setBackgroundImage:segmentedControl forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

//設定UISegmentedControl在被選擇時的背景影像
UIImage *segmentedControl2 = [UIImage imageNamed:@"UISegmentedControl2"];
[[UISegmentedControl appearance] setBackgroundImage:segmentedControl2 forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];


//設定兩個選項在右邊選項被選擇時它門的交會處的影像
UIImage *selectType1 = [UIImage imageNamed:@"SelectType1"];
[[UISegmentedControl appearance] setDividerImage:selectType1
                                     forLeftSegmentState:UIControlStateNormal
                                     rightSegmentState:UIControlStateSelected
                                     barMetrics:UIBarMetricsDefault];

//設定兩個選項在左邊選項被選擇時它門的交會處的影像
UIImage *SelectType2 = [UIImage imageNamed:@"SelectType2"];
[[UISegmentedControl appearance] setDividerImage:SelectType2
                                     forLeftSegmentState:UIControlStateSelected
                                     rightSegmentState:UIControlStateNormal
                                     barMetrics:UIBarMetricsDefault];

//設定UISegmentedControl的字形
[[UISegmentedControl appearance] setTitleTextAttributes:textAttributes forState:UIControlStateNormal];

由於本範例中的 UISegmentedControl 只有兩個項目可以選擇,因此在設定上少設定了當兩邊選項都未被選擇時它的交會處的影像(並不會有兩邊選項都被選擇時的情況)。

在文章的程式碼中有提及過 UIControlStateNormal 這個 UIControlState 屬性,它被定義在 UIControl.h 中,UIControlState 有以下幾種不同的數值。
enum {
    UIControlStateNormal      = 0,
    UIControlStateHighlighted = 1 << 0, // used when UIControl isHighlighted is set
    UIControlStateDisabled    = 1 << 1,
    UIControlStateSelected    = 1 << 2, // flag usable by app (see below)
    UIControlStateApplication = 0x00FF0000, // additional flags available for application use
    UIControlStateReserved    = 0xFF000000 // flags reserved for internal framework use
};
typedef NSUInteger UIControlState;

並非所有物件在設定上都通吃這些屬性,錯誤的使用 UIControlState 很有可能會發生 Error 的窘境。


其他
最後關於使用 Appearance 方法來改變介面外觀並非只有限制範例中上這幾種物件,當然它門的原理大致上都相同,如果因為操作而導致你所設定的圖片變形或是失真等行況可以參考重複影像遮罩的設定方法ㄧ文(在設定 UISlider 時如果圖片大小與物件大小不符就很長發生此行況)。

PS:在使用 Appearance 方法自定物件外觀時必須注意,所有改變外觀的行為必須要在物件被建立之前就要完成,例如你套用一個按扭來觸發 Appearance 方法改變畫面上已經存在的物件外觀,那麼它們將不會有任何改變,反而是你觸發 Appearance 方法之後才建立的物件,才會使用這些新外觀。






3 則留言:

  1. 您好:
    想請問我在實作back按鈕的appearance時使用以下的code
    UIImage *buttonback = [[UIImage imageNamed:@"back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, -1)];
    [[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonback forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

    但是back的文字會出現並蓋在按鈕上, 請問我該怎麼把back消除

    回覆刪除
  2. could 您好:

    按鈕上出現「back」的字樣,是由系統自動生成的,所以修改樣式並無法修改上面的字樣,你可以試試看以下的方式來修改它:

    「方法A:」
    直接設定 backBarButtonItem 的字串,給予它一個空字串,一定要保留空白字元,否則按鈕會不見。
    [self.navigationItem.backBarButtonItem setTitle:@" "];


    「方法B:」
    製作一個全新的 backBarButtonItem,在加入到您的 navigationItem 中。
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
    initWithTitle:@"回到上一頁"
    style:UIBarButtonItemStylePlain
    target:self
    action:nil];

    self.navigationItem.backBarButtonItem = backButton;


    最後提醒您,我猜想您應該是在製作 UITable 時遇到這些問題,由於 backBarButtonItem 雖然和其他的 UIBarButtonItem 一樣都可以自定(像是 rightBarButtonItem 或是 leftBarButtonItem),但是 backBarButtonItem 比較特別,在插入修改它的程式碼時,記得是要在 Master 頁面中,而不是 Detail 頁面,即使 backBarButtonItem 是出現在 Detail 頁面上,但它仍然是屬於 Master 頁面下的東西。


    希望你能順利排除問題!

    回覆刪除
    回覆
    1. 我用方法B讓我的問題排除了~

      真是太感謝了:)

      刪除