programing tip

iOS 8에서 방향 변경을 처리하는 "올바른"방법은 무엇입니까?

itbloger 2020. 8. 20. 07:55
반응형

iOS 8에서 방향 변경을 처리하는 "올바른"방법은 무엇입니까?


누군가 iOS 8에서 세로 및 가로 인터페이스 방향으로 작업하는 데 "올바른"또는 "가장 좋은"접근 방식을 알려주시겠습니까? 그 목적으로 사용하려는 모든 기능이 iOS 8에서 더 이상 사용되지 않는 것 같습니다. 그리고 내 연구에 따르면 명확하고 우아한 대안이 없습니다. 가로 모드인지 세로 모드인지 스스로 결정하기 위해 너비와 높이를 확인해야합니까?

예를 들어, 뷰 컨트롤러에서 다음 의사 코드를 어떻게 구현해야합니까?

if we are rotating from portrait to landscape then
  do portrait things
else if we are rotating from landscape to portrait then
  do landscape things

Apple은 UI가 레이아웃과 모양을 크게 변경할 수 있도록 크기 클래스를 사용 가능한 화면 공간의 대략적인 척도로 사용할 것을 권장합니다. 세로 모드의 iPad는 가로 모드 (일반 너비, 일반 높이)와 동일한 크기 등급을 가지고 있다고 가정합니다. 이는 UI가 두 방향간에 다소 유사해야 함을 의미합니다.

그러나 iPad에서 세로에서 가로로의 변경은 크기 클래스가 변경되지 않았더라도 UI를 약간 조정해야 할만큼 충분히 중요합니다. 의 인터페이스 방향 관련 메서드 UIViewController가 더 이상 사용되지 않으므로 Apple은 이제 다음과 같은 새로운 메서드를 UIViewController대체로 구현할 것을 권장합니다 .

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    // Code here will execute before the rotation begins.
    // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Place code here to perform animations during the rotation.
        // You can pass nil or leave this block empty if not necessary.

    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Code here will execute after the rotation has finished.
        // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]

    }];
}

큰! 이제 순환이 시작되기 직전과 완료된 후에 콜백을받습니다. 그러나 회전이 세로인지 가로인지 실제로 아는 것은 어떨까요?

Apple은 회전을 단순히 상위 뷰의 크기 변경으로 생각할 것을 권장합니다. 즉, 세로에서 가로로 아이 패드 회전하는 동안, 당신은 루트 레벨보기는 단순히 변화로 생각할 수 bounds.size에서 {768, 1024}까지 {1024, 768}. 이를 알면 sizeviewWillTransitionToSize:withTransitionCoordinator:메서드에 전달 된를 사용하여 세로 또는 가로로 회전하는지 파악 해야합니다 .

레거시 코드를 새로운 iOS 8 방식으로 마이그레이션하는보다 원활한 방법을 원한다면 UIView 에서이 간단한 범주사용하는 것이 좋습니다. 이 범주 를 사용하여 뷰가 "세로"인지 또는 "가로"인지 여부를 결정하는 데 사용할 수 있습니다. 크기.

요약하자면:

  1. 크기 클래스를 사용하여 근본적으로 다른 UI를 표시 할시기를 결정해야합니다 (예 : "iPhone과 유사한"UI 대 "iPad와 유사한"UI).
  2. iPad가 회전 할 때와 같이 크기 클래스 변경 되지 않고 컨테이너 (상위보기) 크기가 변경 될 때 UI를 더 작게 조정해야하는 경우 viewWillTransitionToSize:withTransitionCoordinator:UIViewController 에서 콜백을 사용하십시오 .
  3. 앱의 모든 뷰는 레이아웃에 주어진 공간에 따라 레이아웃을 결정해야합니다. 뷰의 자연스러운 계층 구조가이 정보를 계단식으로 배열하도록합니다.
  4. 마찬가지로 statusBarOrientation기본적으로 장치 수준 속성 인를 사용하여 "세로"와 "가로"보기를 레이아웃할지 여부를 결정 하지 마십시오 . 상태 표시 줄 방향은 UIWindow실제로 앱의 가장 루트 수준에있는 것과 같은 것을 처리하는 코드에서만 사용해야 합니다.

smileyborg의 매우 상세한 (및 수용된) 답변을 기반으로하여 다음은 신속한 3을 사용한 적응입니다.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: nil, completion: {
        _ in
        self.collectionView.collectionViewLayout.invalidateLayout()
    })        
}

그리고 UICollectionViewDelegateFlowLayout구현에서

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    // retrieve the updated bounds
    let itemWidth = collectionView.bounds.width
    let itemHeight = collectionView.bounds.height
    // do whatever you need to do to adapt to the new size
}

알림 센터를 사용합니다.

방향 변수 추가 (마지막에 설명)

//Above viewdidload
var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation

보기가 나타날 때 알림 추가

override func viewDidAppear(animated: Bool) {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
}

보기가 사라질 때 알림 제거

override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil) 
}

Gets current orientation when notification is triggered

func orientationChanged (notification: NSNotification) {
    adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
}

Checks orientation (portrait/landscape) and handles events

func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
    if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
    {
        if(orientation != orientations) {
            println("Portrait")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
    else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
    {
       if(orientation != orientations) {
            println("Landscape")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
}

The reason I add an orientation variable is because when testing on a physical device the orientation notification gets called at every minor move in the device, and not just when it rotates. Adding the var and if statements only calls the code if it switched to the opposite orientation.


From a UI perspective, I believe that using Size Classes are Apple's recommended approach for handling interfaces in different orientations, sizes and scales.

See the section: Traits Describe the Size Class and Scale of an Interface here: https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html

"iOS 8 adds new features that make dealing with screen size and orientation much more versatile."

This one is a good article as well: https://carpeaqua.com/thinking-in-terms-of-ios-8-size-classes/

EDIT Updated Link: https://carpeaqua.com/2014/06/14/thinking-in-terms-of-ios-8-size-classes/ (Credit: Koen)

참고URL : https://stackoverflow.com/questions/26069874/what-is-the-right-way-to-handle-orientation-changes-in-ios-8

반응형