如何在更改 UIView 大小时应用动画? + 斯威夫特 5

Posted

技术标签:

【中文标题】如何在更改 UIView 大小时应用动画? + 斯威夫特 5【英文标题】:How to Apply Animation while changing UIView size? + Swift 5 【发布时间】:2020-06-24 12:19:08 【问题描述】:

我是 ios 开发新手,我在 UIView 中有两个按钮,当用户选择选项 portraitlandscape 时,更改 UIView 重新调整大小并更改背景颜色,我需要为那个过程。 例如: 用户选择portrait,然后用户可以看到红色的 UIVIew。单击landscape 选项后,应该开始动画,看起来像,红色图像出现在前面并更改landscape 模式的大小(更改高度和宽度),然后转到上一个位置并将颜色更改为绿色。我在代码中添加了小的 UIView 动画,它有助于您确定我们应该从哪里开始动画并完成它。如果有人知道如何正确操作,请告诉我并感谢您的帮助。请参考下面的代码

import UIKit

class ViewController: UIViewController 
    
    let portraitWidth : CGFloat = 400
    let portraitHeight : CGFloat = 500
    
    let landscapeWidth : CGFloat = 700
    let landscapeHeight : CGFloat = 400
    
    var mainView: UIView!
    var mainStackView: UIStackView!
    
    let segment: UISegmentedControl = 
        let segementControl = UISegmentedControl()
        return segementControl
    ()
    
    override func viewDidLoad() 
        super.viewDidLoad()
        self.view.translatesAutoresizingMaskIntoConstraints = false
        
        mainStackView = UIStackView()
        mainStackView.axis = .vertical
        mainStackView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.alignment = .center
        mainStackView.distribution = .equalCentering
        self.view.addSubview(mainStackView)
        
        self.segment.insertSegment(withTitle: "Portrait", at: 0, animated: false)
        self.segment.insertSegment(withTitle: "Landscape", at: 1, animated: false)
        self.segment.selectedSegmentIndex = 0
        self.segment.addTarget(self, action: #selector(changeOrientation(_:)), for: .valueChanged)
        self.segment.translatesAutoresizingMaskIntoConstraints = false
        self.segment.selectedSegmentIndex = 0
        mainStackView.addArrangedSubview(self.segment)
        
        let safeAreaLayoutGuide = self.view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            self.mainStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 20),
            self.mainStackView.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor, constant: 0),
        ])
        
        NSLayoutConstraint.activate([
            self.segment.heightAnchor.constraint(equalToConstant: 35),
            self.segment.widthAnchor.constraint(equalToConstant: 300)
        ])
        
        mainView = UIView(frame: .zero)
        mainView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.addArrangedSubview(mainView)
        mainView.backgroundColor = UIColor.red
        NSLayoutConstraint.activate([
            mainView.heightAnchor.constraint(equalToConstant: portraitHeight),
            mainView.widthAnchor.constraint(equalToConstant: portraitWidth),
            mainView.topAnchor.constraint(equalTo: segment.bottomAnchor, constant: 30)
        ])
        
    
    
    @IBAction func changeOrientation(_ sender: UISegmentedControl) 
        self.mainView.constraints.forEach (constraint) in
            self.mainView.removeConstraint(constraint)
        
        UIView.animate(withDuration: 1.0) 
            if (sender.selectedSegmentIndex == 0) 
                self.mainView.backgroundColor = UIColor.red
                NSLayoutConstraint.activate([
                    self.mainView.heightAnchor.constraint(equalToConstant: self.portraitHeight),
                    self.mainView.widthAnchor.constraint(equalToConstant: self.portraitWidth),
                    self.mainView.topAnchor.constraint(equalTo: self.segment.bottomAnchor, constant: 30)
                ])
             else 
                self.mainView.backgroundColor = UIColor.green
                NSLayoutConstraint.activate([
                    self.mainView.heightAnchor.constraint(equalToConstant: self.landscapeHeight),
                    self.mainView.widthAnchor.constraint(equalToConstant: self.landscapeWidth),
                    self.mainView.topAnchor.constraint(equalTo: self.segment.bottomAnchor, constant: 30)
                ])
            
        
    
    
    

更新逻辑

@IBAction func changeOrientation(_ sender: UISegmentedControl) 
    UIView.animate(withDuration: 4.0) 
        if (sender.selectedSegmentIndex == 0) 
            self.mainView.backgroundColor = UIColor.red
            self.widthConstraint.constant = self.portraitWidth
            self.heightConstraint.constant = self.portraitWidth
         else 
            self.mainView.backgroundColor = UIColor.green
            self.widthConstraint.constant = self.landscapeWidth
            self.heightConstraint.constant = self.landscapeHeight
        
        self.mainView.layoutIfNeeded()
     

【问题讨论】:

仅供参考,viewDidLoad 和其他地方的所有“自我”都没有任何目的。 @Fattie 是的,为了测试,我已经在 viewDidLoad 方法下添加了所有这些,我想这是在这里提问的简单方法,所有东西都在一个方法中:) 嗨,迪丽热巴!我已经给出了答案。为了清楚我的意思是你可以删除“自我”。那里。 self.view.addSubview 是错误的。它应该是view.addSubview。祝你好运! 【参考方案1】:

有可能,基本问题是:

• 不可能在一个约束和另一个约束之间设置一个实际的变化

要更改大小或形状,您只需为约束的长度设置动画即可。


在您学习的同时,我真的强烈建议您简单地为约束设置动画。

因此,不要尝试“更改”约束,只需为其中一个或另一个的长度设置动画

yourConstraint.constant = 99  // it's that easy

我也真心建议你把它放在故事板上。

你必须先掌握它!

堆栈视图也没有任何理由,现在摆脱它。

只要有一个出口

 @IBOutlet var yourConstraint: NSLayoutConstraint!

和动画

    UIView.animateWithDuration(4.0) 
        self.yourConstraint.constant = 666
        self.view.layoutIfNeeded()
    

请务必在 Stack Overflow 中搜索“iOS 动画约束”,因为要学习的内容很多。

在情节提要上执行此操作,这么简单的事情最多需要 20 秒。一旦你掌握了故事板,只有在有理由的情况下才能继续编写代码

忘记堆栈视图

只需对约束的常量进行动画处理,即可更改大小、形状或您喜欢的任何内容。

请务必在 SO 和其他网站上搜索许多精彩的文章“iOS 中的动画约束”!

【讨论】:

感谢您的评论和建议。我检查了这段代码,它与上面代码中的现有动画非常相似:),没什么特别的,我可以将动画应用到正常方式,但在这里我需要应用一些自定义动画。我认为您没有正确回答我的问题,当您有空时,如果您能再次查看我的任务描述,不胜感激:) 感谢您的帮助 嗨@DileepaChandrasekara,如果我不理解,对不起。您是否意识到您忘记调用 layoutIfNeeded ???例如,***.com/a/36626232/294884 在某些情况下您确实需要重新布局 我调用了它,但什么也没发生 :(,我试图找到一篇文章如何在 swift 5.1 中的动画中更改约束常量 我根据您的评论更新了逻辑,请在更新的逻辑标题下检查它 @DileepaChandrasekara 您无法将 CHANGE 从一个约束设置为另一个约束。

以上是关于如何在更改 UIView 大小时应用动画? + 斯威夫特 5的主要内容,如果未能解决你的问题,请参考以下文章

使用自动调整子视图大小为 UIView 帧大小更改动画

iOS:UIView 在动画时改变大小,我该如何防止?

调整 UIView 大小时动画无法按预期工作

拖动 UIView 时如何实现流畅的动画

如何在移动时调整 UIView 的大小,就像 SnapGuide 一样?

如何在滚动时更改 UIView 大小并延迟