Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレ...

Yuji Hato
September 13, 2018

iOS Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -

iOS Adaptive UI - To the optimum layout corresponding to devices and screen orientations with different resolutions -

Yuji Hato

September 13, 2018
Tweet

More Decks by Yuji Hato

Other Decks in Technology

Transcript

  1. public protocol UITraitEnvironment : NSObjectProtocol { @available(iOS 8.0, *) public

    var traitCollection: UITraitCollection { get } @available(iOS 8.0, *) public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) } 4J[F$MBTTFT
  2. open class UIView : UIResponder, NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment,

    UICoordinateSpace, UIFocusItem, CALayerDelegate { open class UIViewController : UIResponder, NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment { 4J[F$MBTTFT
  3. public protocol UITraitEnvironment : NSObjectProtocol { @available(iOS 8.0, *) public

    var traitCollection: UITraitCollection { get } @available(iOS 8.0, *) public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) } 4J[F$MBTTFT
  4. @available(iOS 8.0, *) open class UITraitCollection : NSObject, NSCopying, NSSecureCoding

    { open var userInterfaceIdiom: UIUserInterfaceIdiom { get } open var displayScale: CGFloat { get } open var horizontalSizeClass: UIUserInterfaceSizeClass { get } open var verticalSizeClass: UIUserInterfaceSizeClass { get } @available(iOS 9.0, *) open var forceTouchCapability: UIForceTouchCapability { get } @available(iOS 10.0, *) open var layoutDirection: UITraitEnvironmentLayoutDirection { get } @available(iOS 10.0, *) open var preferredContentSizeCategory: UIContentSizeCategory { get } @available(iOS 10.0, *) open var displayGamut: UIDisplayGamut { get } … } 4J[F$MBTTFT
  5. @available(iOS 8.0, *) open class UITraitCollection : NSObject, NSCopying, NSSecureCoding

    { open var userInterfaceIdiom: UIUserInterfaceIdiom { get } open var displayScale: CGFloat { get } open var horizontalSizeClass: UIUserInterfaceSizeClass { get } open var verticalSizeClass: UIUserInterfaceSizeClass { get } @available(iOS 9.0, *) open var forceTouchCapability: UIForceTouchCapability { get } @available(iOS 10.0, *) open var layoutDirection: UITraitEnvironmentLayoutDirection { get } @available(iOS 10.0, *) open var preferredContentSizeCategory: UIContentSizeCategory { get } @available(iOS 10.0, *) open var displayGamut: UIDisplayGamut { get } … } 4J[F$MBTTFT
  6. extension UITraitCollection { var isPortrait: Bool { return verticalSizeClass ==

    .regular && horizontalSizeClass == .compact } var isLandscape: Bool { return verticalSizeClass == .compact && horizontalSizeClass == .regular } var isCompactLandscape: Bool { return verticalSizeClass == .compact && horizontalSizeClass == .compact } var isRegularRegular: Bool { return verticalSizeClass == .regular && horizontalSizeClass == .regular } } 4J[F$MBTTFT
  7. public protocol UITraitEnvironment : NSObjectProtocol { @available(iOS 8.0, *) public

    var traitCollection: UITraitCollection { get } @available(iOS 8.0, *) public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) } 4J[F$MBTTFT
  8. 4J[F$MBTTFT iPhone ॳظදࣔ viewDidLoad viewWillAppear traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear ճస࣌

    willTransition(to:with:) viewWillTransition(to:with:) traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews iPad ॳظදࣔ viewDidLoad viewWillAppear traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear ճస࣌ (traitCollection͕มߋͳ͍৔߹) viewWillTransition(to:with:) viewWillLayoutSubviews viewDidLayoutSubviews
  9. 4J[F$MBTTFT iPhone ॳظදࣔ viewDidLoad viewWillAppear traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear ճస࣌

    willTransition(to:with:) viewWillTransition(to:with:) traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews iPad ॳظදࣔ viewDidLoad viewWillAppear traitCollectionDidChange viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear ճస࣌ (traitCollection͕มߋͳ͍৔߹) viewWillTransition(to:with:) viewWillLayoutSubviews viewDidLayoutSubviews
  10. 1SBDUJDF 4UBDL7JFX 4DSPMM7JFX 4UBDL7JFX 7*FX 7*FX 7*FX -FGU7JFX *NBHF7JFX 4UBDL7JFX

    4DSPMM7JFX 4UBDL7JFX 7*FX 7*FX 7*FX -FGU7JFX *NBHF7JFX
  11. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.isPortrait {

    if rootStackView.arrangedSubviews.contains(leftView) { rootStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.insertArrangedSubview(leftView, at: 0) } } else { if scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !rootStackView.arrangedSubviews.contains(leftView) { rootStackView.insertArrangedSubview(leftView, at: 0) } } } 1SBDUJDF
  12. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.isPortrait {

    if rootStackView.arrangedSubviews.contains(leftView) { rootStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.insertArrangedSubview(leftView, at: 0) } } else { if scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !rootStackView.arrangedSubviews.contains(leftView) { rootStackView.insertArrangedSubview(leftView, at: 0) } } } 1SBDUJDF
  13. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.isPortrait {

    if rootStackView.arrangedSubviews.contains(leftView) { rootStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.insertArrangedSubview(leftView, at: 0) } } else { if scrollableStackView.arrangedSubviews.contains(leftView) { scrollableStackView.removeArrangedSubview(leftView) leftView.removeFromSuperview() } if !rootStackView.arrangedSubviews.contains(leftView) { rootStackView.insertArrangedSubview(leftView, at: 0) } } } 1SBDUJDF
  14. static func cellSize(isPortrait: Bool, parentSize: CGSize, isRegularRegular: Bool, safeArea: UIEdgeInsets)

    -> CGSize { let nextContentRatio: Double = 0.2 // νϥݟͤൺ཰ʢద౰ʣ let numberOfItems: Double = isPortrait ? 2 : 4 // (W:C, H:R͸)2ͭɺͦΕҎ֎͸4ͭ let numberOfItemsFactor: Double = numberOfItems + nextContentRatio let sideMargin: CGFloat = isRegularRegular ? 60 : 12 let cellSpace: CGFloat = 24 let margin = sideMargin + safeArea.left + safeArea.right let totalCellSpace: CGFloat = margin + cellSpace * CGFloat(numberOfItems) let remainWidth = parentSize.width - totalCellSpace let width = remainWidth / CGFloat(numberOfItemsFactor) let textAreaHeight: CGFloat = isRegularRegular ? 120 : 80 let thumbnailHeight = width / 16 * 9 let height = thumbnailHeight + textAreaHeight return CGSize(width: width, height: height) } 1SBDUJDF ے೑
  15. static func cellSize(isPortrait: Bool, parentSize: CGSize, isRegularRegular: Bool, safeArea: UIEdgeInsets)

    -> CGSize { let nextContentRatio: Double = 0.2 // νϥݟͤൺ཰ʢద౰ʣ let numberOfItems: Double = isPortrait ? 2 : 4 // (W:C, H:R͸)2ͭɺͦΕҎ֎͸4ͭ let numberOfItemsFactor: Double = numberOfItems + nextContentRatio let sideMargin: CGFloat = isRegularRegular ? 60 : 12 let cellSpace: CGFloat = 24 let margin = sideMargin + safeArea.left + safeArea.right let totalCellSpace: CGFloat = margin + cellSpace * CGFloat(numberOfItems) let remainWidth = parentSize.width - totalCellSpace let width = remainWidth / CGFloat(numberOfItemsFactor) let textAreaHeight: CGFloat = isRegularRegular ? 120 : 80 let thumbnailHeight = width / 16 * 9 let height = thumbnailHeight + textAreaHeight return CGSize(width: width, height: height) } 1SBDUJDF
  16. static func cellSize(isPortrait: Bool, parentSize: CGSize, isRegularRegular: Bool, safeArea: UIEdgeInsets)

    -> CGSize { let nextContentRatio: Double = 0.2 // νϥݟͤൺ཰ʢద౰ʣ let numberOfItems: Double = isPortrait ? 2 : 4 // (W:C, H:R͸)2ͭɺͦΕҎ֎͸4ͭ let numberOfItemsFactor: Double = numberOfItems + nextContentRatio let sideMargin: CGFloat = isRegularRegular ? 60 : 12 let cellSpace: CGFloat = 24 let margin = sideMargin + safeArea.left + safeArea.right let totalCellSpace: CGFloat = margin + cellSpace * CGFloat(numberOfItems) let remainWidth = parentSize.width - totalCellSpace let width = remainWidth / CGFloat(numberOfItemsFactor) let textAreaHeight: CGFloat = isRegularRegular ? 120 : 80 let thumbnailHeight = width / 16 * 9 let height = thumbnailHeight + textAreaHeight return CGSize(width: width, height: height) } 1SBDUJDF
  17. static func cellSize(isPortrait: Bool, parentSize: CGSize, isRegularRegular: Bool, safeArea: UIEdgeInsets)

    -> CGSize { let nextContentRatio: Double = 0.2 // νϥݟͤൺ཰ʢద౰ʣ let numberOfItems: Double = isPortrait ? 2 : 4 // (W:C, H:R͸)2ͭɺͦΕҎ֎͸4ͭ let numberOfItemsFactor: Double = numberOfItems + nextContentRatio let sideMargin: CGFloat = isRegularRegular ? 60 : 12 let cellSpace: CGFloat = 24 let margin = sideMargin + safeArea.left + safeArea.right let totalCellSpace: CGFloat = margin + cellSpace * CGFloat(numberOfItems) let remainWidth = parentSize.width - totalCellSpace let width = remainWidth / CGFloat(numberOfItemsFactor) let textAreaHeight: CGFloat = isRegularRegular ? 120 : 80 let thumbnailHeight = width / 16 * 9 let height = thumbnailHeight + textAreaHeight return CGSize(width: width, height: height) } 1SBDUJDF
  18. override func overrideTraitCollection(forChildViewController childViewController: UIViewController) -> UITraitCollection? { if UIDevice.current.userInterfaceIdiom

    == .pad, let rootViewController = UIApplication.shared.keyWindow?.rootViewController { let portraitTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .regular)]) let landscapeTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .compact)]) let rootViewSize = rootViewController.view.bounds.size let size = view.bounds.size if isMultiTasking(rootViewSize: rootViewSize) { if rootViewController.traitCollection.isRegularRegular { return landscapeTraitCollection } else { return portraitTraitCollection } } else if size.width > size.height { return landscapeTraitCollection } else { return portraitTraitCollection } } return traitCollection } 1SBDUJDF
  19. override func overrideTraitCollection(forChildViewController childViewController: UIViewController) -> UITraitCollection? { if UIDevice.current.userInterfaceIdiom

    == .pad, let rootViewController = UIApplication.shared.keyWindow?.rootViewController { let portraitTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .regular)]) let landscapeTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .compact)]) let rootViewSize = rootViewController.view.bounds.size let size = view.bounds.size if isMultiTasking(rootViewSize: rootViewSize) { if rootViewController.traitCollection.isRegularRegular { return landscapeTraitCollection } else { return portraitTraitCollection } } else if size.width > size.height { return landscapeTraitCollection } else { return portraitTraitCollection } } return traitCollection } 1SBDUJDF
  20. override func overrideTraitCollection(forChildViewController childViewController: UIViewController) -> UITraitCollection? { if UIDevice.current.userInterfaceIdiom

    == .pad, let rootViewController = UIApplication.shared.keyWindow?.rootViewController { let portraitTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .regular)]) let landscapeTraitCollection = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .compact), UITraitCollection(verticalSizeClass: .compact)]) let rootViewSize = rootViewController.view.bounds.size let size = view.bounds.size if isMultiTasking(rootViewSize: rootViewSize) { if rootViewController.traitCollection.isRegularRegular { return landscapeTraitCollection } else { return portraitTraitCollection } } else if size.width > size.height { return landscapeTraitCollection } else { return portraitTraitCollection } } return traitCollection } 1SBDUJDF