简体   繁体   English

景观方向的不同视图/布局

[英]Different View/Layout for Landscape Orientation

I am building a calculator app and have it working in portrait mode.我正在构建一个计算器应用程序并让它在纵向模式下工作。 However, I want the user to have more options/functions when they switch to landscape mode.但是,我希望用户在切换到横向模式时有更多选项/功能。 In other words, the entire layout would have to change as there will be more buttons in landscape mode compared to portrait mode.换句话说,整个布局必须改变,因为与纵向模式相比,横向模式会有更多的按钮。

I have managed to do this using the installed property under the attribute inspector.我已经使用属性检查器下的installed属性设法做到了这一点。 Here are the problems I am running into:以下是我遇到的问题:

  1. When I run the app in portrait mode and rotate it to landscape, I will show the buttons but they are overlapped.当我以纵向模式运行应用程序并将其旋转为横向时,我将显示按钮,但它们是重叠的。 Here is a demo(Just wait for the gif to restart):这是一个演示(只需等待 gif 重新启动):

在此处输入图片说明

  1. When I run the app in landscape mode, it displays all the buttons correctly, but as soon as I rotate it again to portrait and then back to landscape, the same problem as #1 happens.当我在横向模式下运行应用程序时,它会正确显示所有按钮,但是一旦我再次将其旋转为纵向然后再旋转回横向,就会发生与 #1 相同的问题。 Here is a demo (Just wait for the gif to restart):这是一个演示(只需等待 gif 重新启动):

在此处输入图片说明

What am I doing wrong?我究竟做错了什么? How can I resolve this?我该如何解决这个问题?

Here's what I've been doing since iOS9.这是我自 iOS9 以来一直在做的事情。 Complete code, does not assume you are using IB (I actually think you should not) and should help you with how auto layout works.完整代码,您使用的IB承担(其实我觉得你不应该),并应帮助你自动布局是如何工作的。 BEWARE, this does assume some knowledge of auto layout and Swift.当心,这确实需要一些自动布局和 Swift 的知识。 This also deals with a very simple example of a UIButton .这也涉及一个非常简单的UIButton示例。

First, declare two arrays of constraints, typically in the view controller:首先,声明两个约束数组,通常在视图控制器中:

var landscape = [NSLayoutConstraint]()
var portrait = [NSLayoutConstraint]()
var myButton = UIButton()

Next, set up your constant constraints and set the active:接下来,设置常量约束并设置活动:

myButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myButton)
myButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
myButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
myButton.widthAnchor.constraint(equalToConstant: 200).isActive = true

So far, so good.到现在为止还挺好。 You've created a button, added it to the VC view, declared it's size as 40x200.您已经创建了一个按钮,将其添加到 VC 视图中,并声明其大小为 40x200。 You've also declared it to be anchored to the parent's safeAreaLayoutGuide top anchor.您还声明它锚定到父级的safeAreaLayoutGuide顶部锚点。

Now, it's time for the "magic".现在,是时候发挥“魔法”了。 You wish to move this UIButton from the bottom to the right depending on orientation.您希望根据方向将此UIButton从底部向右移动。 (Please note, while certain overrides will work on iPhones, iPads, when full screen, will always have a "Regular" size class - in full screen - no matter the orientation!) (请注意,虽然某些覆盖可以在 iPhone 上运行,但在全屏时 iPad 将始终具有“常规”尺寸类别 - 全屏 - 无论方向如何!)

The first thing you need is to put the remaining constraints into the arrays you declared.您需要做的第一件事是将剩余的约束放入您声明的数组中。

portrait.append(myButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10))
landscape.append(myButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10))

Now you have s single constraint to activate.现在您需要激活单个约束。 It can be more, remember we are talking arrays.可以更多,记住我们说的是数组。 This is simple, just deactivate and activate as needed:这很简单,只需根据需要停用和激活:

func changeConstraints() {
    if isInPortrait {
        NSLayoutConstraint.deactivate(landscape)
        NSLayoutConstraint.activate(portrait)
    } else {
        NSLayoutConstraint.deactivate(portrait)
        NSLayoutConstraint.activate(landscape)
    }
}

You can even animate things is you wish!您甚至可以根据自己的意愿为事物设置动画! Finally, let's tap into the VC life cycle.最后,让我们进入 VC 生命周期。 I'm very sure there are other (and better) ways, but keep in mind what I mentioned earlier - in full screen, an iPad will always have a Regular size class.确定还有其他(和更好的)方法,但请记住我之前提到的 - 在全屏模式下,iPad 将始终具有常规尺寸等级。 So I prefer to dig just a bit deeper.所以我更喜欢深入挖掘。 I tend to use three variables - you probably need less.我倾向于使用三个变量——你可能需要的更少。

var initialOrientation = true
var isInPortrait = false
var orientationDidChange = false

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if initialOrientation {
        initialOrientation = false
        if view.frame.width > view.frame.height {
            isInPortrait = false
        } else {
            isInPortrait = true
        }
        changeConstraints()
    } else {
        if view.orientationHasChanged(&isInPortrait) {
            changeConstraints()
        }
    }
}

I also have an extension to UIView :我也有UIView的扩展:

extension UIView {
    func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool {
        if self.frame.width > self.frame.height {
            if isInPortrait {
                isInPortrait = false
                return true
            }
        } else {
            if !isInPortrait {
                isInPortrait = true
                return true
            }
        }
        return false
    }
}

I think this should describe most of my code.我认为这应该描述我的大部分代码。 Basically, (a) do not use UIDevice nor (b) use viewWillTransition(toSize:) and check a size class when working with a iPad.基本上,(a)使用UIDevice或 (b) 使用viewWillTransition(toSize:)并在使用 iPad 时检查大小类。 (They will have a size class change - albeit differently on devices depending on size, but only when in split screen mode. At least for now!) (它们有一个尺寸等级变化 - 尽管根据尺寸在设备上有所不同,但仅限于在分屏模式下。至少现在!)

Pretty much, use (a) view willLayoutSubviews - you can use view DidLayoutSubviews but I prefer doing things at the earliest point possible - and then (b) check the actual screen size. view willLayoutSubviews ,使用 (a) view willLayoutSubviews - 你可以使用view DidLayoutSubviews但我更喜欢尽早做事 - 然后 (b) 检查实际屏幕尺寸。

You can use iOS orientation change method in view controller class life cycle.您可以在视图控制器类生命周期中使用 iOS 方向更改方法。

First you have to make all the appropriate UIs using stackViews and views UI objects.首先,您必须使用 stackViews 和视图 UI 对象制作所有适当的 UI。

Then you need to manage your constraints (width, height, ratio of the calculator UI buttons/views using iOS size classes.然后,您需要使用 iOS 大小类来管理您的约束(宽度、高度、计算器 UI 按钮/视图的比率。

Also add this method in your view controller and manage your views visibility还要在您的视图控制器中添加此方法并管理您的视图可见性

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
        // Show your additional UIs elements views for Landscape
    } else {
        print("Portrait")
        // Hide your additional UIs elements / views for Portrait
    }
}

If you want any assistance for making UI sizes, please follow the option below.如果您在制作 UI 尺寸方面需要任何帮助,请按照以下选项进行操作。 So you have to use iOS size classes.所以你必须使用 iOS 大小类。

  1. You can add your constraints to a view and edit it at 'Size Inspector'.您可以将约束添加到视图并在“尺寸检查器”中进行编辑。
  2. Double click the appropriate set constraint and add more required sizes classes using + button just before the the label.双击适当的设置约束并使用标签前的 + 按钮添加更多所需的尺寸类。
  3. Make sure to uncheck the 'Installed' checkbox and check the required sizes (wC,hC / wR, hR / wC, hR / wR, hC) for the selected constraints respectively (Constraints for portrait mode).确保取消选中“已安装”复选框并分别选中所选约束(纵向模式的约束)所需的尺寸(wC、hC / wR、hR / wC、hR / wR、hC)。
  4. Add new constraints for the UIs of landscape mode as well and do the same this as above no.也为横向模式的 UI 添加新的约束,并执行与上述 no 相同的操作。 3 by checking only the size classes for iPhone landscape mode. 3 通过仅检查 iPhone 横向模式的尺寸等级。

Please review the checking options in Xcode here请在此处查看 Xcode 中的检查选项

Helpful links:有用的网址:

https://medium.com/swlh/ios-adaptive-layout-i-size-class-c561bd730e1 https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/ https://medium.com/swlh/ios-adaptive-layout-i-size-class-c561bd730e1 https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and -布局/

I made a sample work for you and added to My GitHub repositories.我为您制作了一个示例工作并添加到我的 GitHub 存储库中。

Please have a look on main.storyboard UI setup and get your work done.请查看 main.storyboard UI 设置并完成您的工作。

Repo: https://github.com/ryra-circuit/DynamicUICalculator回购: https : //github.com/ryra-circuit/DynamicUICalculator

iPhone 11 Portrait iPhone 11 人像

iPhone 11 Landscape iPhone 11 横向

iPhone SE Gen 1 Portrait iPhone SE Gen 1 肖像

iPhone SE Gen 1 Landscape iPhone SE Gen 1 横向

Thanks谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM