2010-05-12 77 views
34

這是一個人們爲我提供指導的一般問題,基本上我在學習iPad/iPhone開發,並最終遇到了多方向支持問題。iphone/ipad方向處理

我已經查找了相當數量的doco,而我的書「Beginning iPhone 3 Development」有一個很好的章節。

但我的問題是,如果我想以編程方式更改我的控件(或者甚至針對每個方向使用不同的視圖),人們如何維護其代碼庫?我可以想象如此多的意大利麪條代碼/成千上萬的「if」檢查問題,它會迫使我對UI界面做一些小改動。

有沒有人有處理這個問題的經驗?什麼是控制它的好方法?

非常感謝 馬克

回答

41

我做到這一點,在我的視圖控制器兩種簡單的方法:

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [self adjustViewsForOrientation:toInterfaceOrientation]; 
} 

- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation { 
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) { 
     titleImageView.center = CGPointMake(235.0f, 42.0f); 
     subtitleImageView.center = CGPointMake(355.0f, 70.0f); 
     ... 
    } 
    else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { 
     titleImageView.center = CGPointMake(160.0f, 52.0f); 
     subtitleImageView.center = CGPointMake(275.0f, 80.0f); 
     ... 
    } 
} 

爲了保持乾淨,你可以很容易地劃分視圖調整/重裝/等。使用從單個條件中調用的方法。

+0

是的,這是有點什麼即時通訊現在做...感謝 – Mark 2010-05-12 02:56:53

+1

對我willRotateToInterface方法永遠不會被調用。你需要連接一些東西,或者在IB中添加一個監聽器嗎? – 2010-08-13 00:38:26

+0

這是我正在尋找的很好的例子。任何替代的例子? – 2010-12-16 09:50:07

2

,如果你把你所有的從你的UI(視圖)分開的邏輯(模型)的iPhone SDK是圍繞在理論上有一個MVC架構,因此建那麼你只需要擔心關於一個地方的用戶界面:你的視圖控制器。對於那些,你可以有一個單獨的視圖控制器爲每個方向,其中每一個然後將被加載一個if/else來選擇加載哪個視圖控制器。

對於iPhone/iPad支持,您可以加載另一個可以處理更大顯示的視圖控制器的相同想法。

+0

是的,我曾見過有人做這樣的事情,它是一個好主意,謝謝 – Mark 2010-05-12 02:57:51

7

這真的取決於你在鋪設什麼。

如果您查看Apple Settings應用程序,您可以看到他們使用表格視圖作爲佈局,併爲大多數行定製了單元格。這樣,您可以通過填充單元格的寬度,以簡單的界面進行相當便宜的旋轉。這甚至適用於郵件,每行都有編輯文本單元的東西。表格可以很容易地全部透明,只有按鈕或標籤可見,所以它們看起來不像表格。

您可以從每個UIView的autoresizingMask中獲得大量的milage。如果您有一個或多個項目可以具有靈活的高度,那麼通常可以獲得在任一方向都看起來很好的界面佈局。根據它的外觀,有時候你可以把所有東西都放在最上面。

在極少數情況下,如果所有界面元素都放在正方形中,您可以將它們旋轉到位。

有兩次您必須明確處理方向更改。一種是在旋轉時視圖從旁邊移動到另一個之下。另一種情況是每個方向都有不同的圖像,例如,如果您始終希望成爲全幅圖像。

有時會有解決這兩個問題的方法。您可以使用可拉伸圖像或將自己限制爲每行一個視圖。或者您可以鎖定某些視圖的方向。

如果您必須更改視圖的佈局,則會有一個明確的layoutSubviews方法。你應該嘗試在這個方法中處理你所有的條件佈局。只有當視圖邊界發生變化時纔會調用它,例如在旋轉時或如果您爲鍵盤騰出空間。爲需要響應旋轉的每個視圖層次結構進行自定義視圖,並從中佈局子視圖。

0

我不能保證這些代碼,並在所有誠實上述willRotateToInterfaceOrientation的偉大工程。這裏是另一個與Facebook的FBDialog.m對iphone/ipad的採訪。 (雖然,我認爲這是對的WebView)

這裏的要點

[[NSNotificationCenter defaultCenter] addObserver:self 
    selector:@selector(deviceOrientationDidChange:) 
    name:@"UIDeviceOrientationDidChangeNotification" object:nil]; 


- (void)deviceOrientationDidChange:(void*)object { 
    UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 
    if ([self shouldRotateToOrientation:orientation]) { 


    CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration; 
    [UIView beginAnimations:nil context:nil]; 
    [UIView setAnimationDuration:duration]; 
    [self sizeToFitOrientation:YES]; 
    [UIView commitAnimations]; 
    } 
} 


-(CGAffineTransform)transformForOrientation { 
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 
    if (orientation == UIInterfaceOrientationLandscapeLeft) { 
    return CGAffineTransformMakeRotation(M_PI*1.5); 
    } else if (orientation == UIInterfaceOrientationLandscapeRight) { 
    return CGAffineTransformMakeRotation(M_PI/2); 
    } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { 
    return CGAffineTransformMakeRotation(-M_PI); 
    } else { 
    return CGAffineTransformIdentity; 
    } 
} 

- (void)sizeToFitOrientation:(BOOL)transform { 
    if (transform) { 
    self.transform = CGAffineTransformIdentity; 
    } 

    CGRect frame = [UIScreen mainScreen].applicationFrame; 
    CGPoint center = CGPointMake(
    frame.origin.x + ceil(frame.size.width/2), 
    frame.origin.y + ceil(frame.size.height/2)); 

    CGFloat scale_factor = 1.0f; 
    if (FBIsDeviceIPad()) { 
    // On the iPad the dialog's dimensions should only be 60% of the screen's 
    scale_factor = 0.6f; 
    } 

    CGFloat width = floor(scale_factor * frame.size.width) - kPadding * 2; 
    CGFloat height = floor(scale_factor * frame.size.height) - kPadding * 2; 

    _orientation = [UIApplication sharedApplication].statusBarOrientation; 
    if (UIInterfaceOrientationIsLandscape(_orientation)) { 
    self.frame = CGRectMake(kPadding, kPadding, height, width); 
    } else { 
    self.frame = CGRectMake(kPadding, kPadding, width, height); 
    } 
    self.center = center; 

    if (transform) { 
    self.transform = [self transformForOrientation]; 
    } 
} 
0

在你的問題,你寫道:

我可以想像的細碼/十萬這麼多問題的「如果」檢查遍佈整個地方,它會迫使我堅決對UI安排做一個小改動。

避免這種情況的一種方法是創建一個視圖層次結構,從一開始就將iPhone/iPad特定更改的處理分開。您只需設置每個設備最初加載的視圖。然後,像通常那樣創建視圖控制器,但是您也創建了您創建的視圖控制器的子類。每個設備的一個子類。這就是您可以放置​​設備特定代碼的位置,例如定位處理。就像這樣:

MyViewController.h   // Code that is used on both devices 
    MyViewController_iPhone.h // iPhone specific code, like orientation handling 
    MyViewController_iPad.h // iPad specific code, like orientation handling 

如果你有興趣在此方法中,我建議你讀this article。它以非常好的方式解釋它。

之一上述文章中提到的事情,是這樣的:

的quote--

這種模式的好處是--start我們沒有垃圾我們的代碼是廢話看起來是這樣的:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 
    // The device is an iPad running iPhone 3.2 or later. 
    // set up the iPad-specific view 
} else { 
    // The device is an iPhone or iPod touch. 
    // set up the iPhone/iPod Touch view 
} 

---年底quote--

我希望有所幫助。祝你好運!