2010-05-12 20 views
34

Đây là câu hỏi chung để mọi người cung cấp cho tôi hướng dẫn, về cơ bản Im học về phát triển iPad/iPhone và cuối cùng đã tìm ra câu hỏi hỗ trợ đa hướng.Xử lý định hướng iphone/ipad

Tôi đã tra cứu một lượng tài liệu hợp lý và cuốn sách "Bắt đầu phát triển iPhone 3" của tôi có một chương hay về nó. Nhưng câu hỏi của tôi là, nếu tôi thay đổi chương trình điều khiển của mình một cách có lập trình (hoặc thậm chí sử dụng các quan điểm khác nhau cho mỗi định hướng), làm thế nào để mọi người duy trì cơ sở mã của họ trên trái đất? Tôi chỉ có thể tưởng tượng rất nhiều vấn đề với mã spaghetti/hàng ngàn "nếu" kiểm tra tất cả các nơi, rằng nó sẽ khiến tôi hạt để thực hiện một thay đổi nhỏ để sắp xếp giao diện người dùng.

Có ai có kinh nghiệm xử lý vấn đề này không? Một cách hay để kiểm soát nó là gì?

Thanks a lot Đánh dấu

Trả lời

41

Tôi làm điều này với hai phương pháp đơn giản trong điều khiển điểm của tôi:

- (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); 
     ... 
    } 
} 

Để giữ này sạch bạn có thể dễ dàng điều chỉnh compartmentalize xem/tải lại/etc. với các phương thức được gọi từ bên trong đơn có điều kiện if-else.

+0

vâng, đây là loại im đang làm ... nhờ – Mark

+1

phương pháp willRotateToInterface cho tôi không bao giờ được gọi. Bạn có phải kết nối một cái gì đó hoặc thêm một người nghe trong IB hoặc một cái gì đó? –

+0

đây là ví dụ tuyệt vời mà tôi đang tìm kiếm. bất kỳ ví dụ thay thế nào? –

2

iPhone SDK được xây dựng xung quanh việc có một kiến ​​trúc MVC, vì vậy về mặt lý thuyết, nếu bạn giữ tất cả các logic của bạn (mô hình) tách ra từ giao diện người dùng của bạn (xem) sau đó bạn sẽ chỉ phải lo lắng về giao diện người dùng tại một điểm: bộ điều khiển chế độ xem của bạn. Đối với những người, bạn có thể có một bộ điều khiển xem riêng biệt cho mỗi định hướng, mỗi trong số đó sau đó sẽ chỉ được nạp với một nếu/else để chọn bộ điều khiển xem để tải.

Cùng một ý tưởng giữ cho hỗ trợ iPhone/iPad, nơi bạn có thể tải một bộ điều khiển chế độ xem khác có thể xử lý các màn hình lớn hơn.

+0

vâng, tôi đã thấy ai đó làm điều gì đó như thế này, một ý tưởng hay, cảm ơn – Mark

7

Nó thực sự phụ thuộc vào những gì bạn đang đặt ra.

Nếu bạn nhìn vào ứng dụng Cài đặt Apple, bạn có thể thấy rằng họ sử dụng chế độ xem bảng cho bố cục, với các ô tùy chỉnh cho hầu hết các hàng. Với điều đó, bạn có thể cho phép một giao diện đơn giản để xoay khá rẻ bằng cách chỉ cần làm đầy chiều rộng của các ô. Điều này thậm chí áp dụng cho những thứ như Mail, nơi có các ô chỉnh sửa văn bản trong mỗi hàng. Và các bảng có thể dễ dàng tất cả trong suốt, chỉ với các nút hoặc nhãn có thể nhìn thấy, vì vậy chúng không giống như các bảng.

Bạn có thể nhận được rất nhiều milage ra khỏi autoresizingMask của mọi UIView. Nếu bạn có một hoặc nhiều mục có thể có chiều cao linh hoạt, thì bạn thường có thể có bố cục giao diện có vẻ tốt trong cả hai hướng. Tùy thuộc vào cách nó trông, đôi khi bạn chỉ có thể ghim mọi thứ lên trên cùng.

Trong trường hợp hiếm hoi, nếu tất cả các phần tử giao diện vừa với hình vuông, bạn chỉ có thể xoay chúng vào vị trí.

Có hai lần bạn phải xử lý rõ ràng các thay đổi định hướng. Một là khi chế độ xem di chuyển từ bên cạnh sang chế độ xem khác khi xoay vòng. Cách khác là khi bạn có các hình ảnh khác nhau cho mỗi hướng, ví dụ nếu bạn luôn muốn có chiều rộng đầy đủ.

Đôi khi có nhiều cách để giải quyết cả hai vấn đề này. Bạn có thể sử dụng hình ảnh có thể kéo dài hoặc giới hạn mình thành một chế độ xem trên mỗi dòng. Hoặc bạn có thể khóa định hướng cho các chế độ xem nhất định.

Nếu bạn phải thay đổi bố cục của chế độ xem, có phương pháp bố cục rõ ràngSubviews.Bạn nên cố gắng xử lý tất cả các bố cục có điều kiện trong phương thức này. Nó chỉ được gọi khi thay đổi giới hạn xem, ví dụ xoay vòng hoặc nếu bạn đã tạo chỗ cho bàn phím. Tạo chế độ xem tùy chỉnh cho từng cấu trúc phân cấp xem cần phản hồi xoay vòng và bố cục các bản xem phụ từ đó.

0

tôi không thể xác minh cho mã này, và trong tất cả sự trung thực các willRotateToInterfaceOrientation trên các công trình lớn. Đây là một mất trên nó với FBDialog.m từ Facebook cho iphone/ipad. (Mặc dù, tôi nghĩ rằng đây là một webview)

đây là ý chính

[[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

Trong câu hỏi của bạn, bạn đã viết:

tôi chỉ có thể tưởng tượng rất nhiều vấn đề với mã spaghetti/ngàn của "if" kiểm tra tất cả các nơi, rằng nó sẽ khiến tôi hạt để thực hiện một thay đổi nhỏ để sắp xếp giao diện người dùng.

Một cách để né tránh điều này là tạo phân cấp chế độ xem chia tách việc xử lý các thay đổi cụ thể của iPhone/iPad ngay từ đầu. Bạn chỉ phải đặt chế độ xem ban đầu được tải cho từng thiết bị. Sau đó, bạn tạo một viewcontroller như bạn thường làm, nhưng bạn cũng phân lớp các viewcontroller bạn đã tạo ra. Một phân lớp cho mỗi thiết bị. Đó là nơi bạn có thể đặt mã cụ thể của thiết bị, như xử lý định hướng. Như thế này:

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 

Nếu bạn quan tâm đến phương pháp này, tôi khuyên bạn nên đọc this article. Nó giải thích nó theo một cách rất hay.

Một trong những điều bài báo đề cập, là thế này:

--start của quote--

Vẻ đẹp của mô hình này là chúng ta không cần phải xả rác mã của chúng tôi với tào lao đó trông như thế này:

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 
} 

--- cuối quote--

Tôi hy vọng điều đó sẽ giúp ích cho bạn. Chúc may mắn!