代码之家  ›  专栏  ›  技术社区  ›  Paresh Navadiya

iOS内容与动画从水平到垂直,反之亦然

  •  1
  • Paresh Navadiya  · 技术社区  · 6 年前

    我们能通过以下方式实现这一点吗 UIStackView 与最初一样 然后最终会是 水平轴 反之亦然?

    如果使用 NSAutoLayout

    需要帮助,如果有人可以提供我的例子来源或任何提示在这里将是有益的。

    I found this Android library

    Need animation like this

    2 回复  |  直到 6 年前
        1
  •  4
  •   Basel    6 年前

    更新答案

    感谢@Fogmeister

    首先,我创建两个堆栈视图

    和bigStackView保持第一个stackView和followButton

    enter image description here

    像这样的约束

    enter image description here

    我之所以在左右两侧添加20个点,是因为如果我将其设置为0,则“跟随”按钮将接近屏幕边缘!

    堆栈视图: 您不需要在此堆栈视图上添加约束

    enter image description here

    可命名:

    enter image description here

    下图:

    enter image description here

    并为stackView添加160点的高约束 向上滚动时将其更改为100点

    代码将变成这样

    import UIKit
    
    class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {
    
        @IBOutlet weak var bigStackView: UIStackView!
    
        @IBOutlet weak var StackView: UIStackView!
    
        @IBOutlet weak var StackViewHight: NSLayoutConstraint!
    
        @IBOutlet weak var progileHight: NSLayoutConstraint!
    
        @IBOutlet weak var profileWidth: NSLayoutConstraint!
    
    
    
        var rowsNames = ["Row 0", "Row 1", "Row 2", "Row 3", "Row 4", "Row 5",
                      "Row 6", "Row 7", "Row 8", "Row 9", "Row 10", "Row 11",
                      "Row 12", "Row 13", "Row 14", "Row 15", "Row 16", "Row 17",
                      "Row 18", "Row 19", "Row 20", "Row 21", "Row 22", "Row 23",
                      "Row 24", "Row 25", "Row 26", "Row 27", "Row 28", "Row 29", "Row 20"]
    
    
    
    
        // we set a variable to hold the contentOffSet before scroll view scrolls
        var lastContentOffset: CGFloat = 0
    
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
        }
    
    
        // MARK: - UITableViewDataSource
    
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return rowsNames.count
    
        }
    
         func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    
            cell.textLabel?.text = rowsNames[indexPath.row]
    
            return cell
        }
    
    
    
        // this delegate is called when the scrollView (i.e your UITableView) will start scrolling
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            self.lastContentOffset = scrollView.contentOffset.y
        }
    
        // while scrolling this delegate is being called so you may now check which direction your scrollView is being scrolled to
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if (self.lastContentOffset < scrollView.contentOffset.y) {
                // moved to top
    
    
                        UIView.animate(withDuration: 0.5,
                                       animations: {
    
    
    // Change Hight and Witdh of profileImage (make it smaller)
    
                                        self.progileHight.constant = 50
                                        self.profileWidth.constant = 50
    
                    self.bigStackView.axis = .horizontal
    
                                        self.StackView.axis = .horizontal
    
                                        // Change spacing between profileImage and nameLable
                                        self.StackView.spacing = 15
    
                                        // Make BigStackView Smaller
                                        self.StackViewHight.constant = 100
    
    
    
                                        self.view.layoutIfNeeded()
    
    
                        })
    
    
    
            } else if (self.lastContentOffset > scrollView.contentOffset.y) {
                // moved to bottom
    
                UIView.animate(withDuration: 0.5,
                               animations: {
    
    
                                // return Hight and Witdh of profileImage to its orginal size
    
                                self.progileHight.constant = 100
                                self.profileWidth.constant = 100
    
    
                                self.bigStackView.axis = .vertical
    
                                self.StackView.axis = .vertical
    
                                // return spacing between profileImage and nameLable to the orginal space
                                self.StackView.spacing = 5
    
                                // return BigStackView to its orginal size 
                                self.StackViewHight.constant = 160
    
    
               self.view.layoutIfNeeded()
    
                                 })
    
            } else {
                // didn't move
            }
        }
    
    
    
    
    
    
    
    }
    

    结果将是:

    enter image description here

    我不认为你能通过UIStackView实现这一点

    但使用UIView很容易做到这一点

    enter image description here

    enter image description here

    UIView:

    enter image description here

    配置文件图像:

    enter image description here

    enter image description here

    以下按钮:

    enter image description here

    我在每台iPhone设备上都做了测试,在iPad上,这种限制并没有打破

    然后你只需要使用UIView。使有生气

    移动物品

    import UIKit
    
    class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {
    
        var rowsNames = ["Row 0", "Row 1", "Row 2", "Row 3", "Row 4", "Row 5",
                      "Row 6", "Row 7", "Row 8", "Row 9", "Row 10", "Row 11",
                      "Row 12", "Row 13", "Row 14", "Row 15", "Row 16", "Row 17",
                      "Row 18", "Row 19", "Row 20", "Row 21", "Row 22", "Row 23",
                      "Row 24", "Row 25", "Row 26", "Row 27", "Row 28", "Row 29", "Row 20"]
    
    
        @IBOutlet weak var squareView: UIView!
    
        @IBOutlet weak var hightView: NSLayoutConstraint!
    
    
    
        @IBOutlet weak var profileImage: UIImageView!
    
        @IBOutlet weak var followButton: UIButton!
    
        @IBOutlet weak var nameLable: UILabel!
    
        // we set a variable to hold the contentOffSet before scroll view scrolls
        var lastContentOffset: CGFloat = 0
    
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
        }
    
    
        // MARK: - UITableViewDataSource
    
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return rowsNames.count
    
        }
    
         func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    
            cell.textLabel?.text = rowsNames[indexPath.row]
    
            return cell
        }
    
    
    
        // this delegate is called when the scrollView (i.e your UITableView) will start scrolling
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            self.lastContentOffset = scrollView.contentOffset.y
        }
    
        // while scrolling this delegate is being called so you may now check which direction your scrollView is being scrolled to
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if (self.lastContentOffset < scrollView.contentOffset.y) {
                // moved to top
    
                        self.hightView.constant = 100
    
    
                        UIView.animate(withDuration: 0.5,
                                       animations: {
    
    
                     self.profileImage.transform = CGAffineTransform(translationX:-150, y: -15).scaledBy(x: 0.5, y: 0.5)
    
    
                     self.followButton.transform = CGAffineTransform(translationX:130, y: -110)
    
                  self.nameLable.transform = CGAffineTransform(translationX:-95, y: -80)
    
    
                                        self.view.layoutIfNeeded()
    
    
                        })
    
    
    
            } else if (self.lastContentOffset > scrollView.contentOffset.y) {
                // moved to bottom
    
                UIView.animate(withDuration: 0.5,
                               animations: {
    
                self.hightView.constant = 206
                self.profileImage.transform = CGAffineTransform.identity
                self.followButton.transform = CGAffineTransform.identity
                self.nameLable.transform = CGAffineTransform.identity
    
                self.view.layoutIfNeeded()
    
                                 })
    
            } else {
                // didn't move
            }
        }
    
    
    
    
    
    
    
    }
    

    我所做的是检测用户是否向上或向下滚动

    我改变了UIView的高度 更改ProfileImage的位置并将其缩小一半 然后更改namaLable和followButton

    我将高尺寸还原为原始尺寸 并使用将其余视图恢复为其原始大小

    CGAffineTransform.identity
    

    结果是

    enter image description here

        2
  •  3
  •   Fogmeister    6 年前

    UIStackView 因为你似乎没有尝试就放弃了它。

    我在这里添加了一个要点和所有代码。代码有点不可靠,因为95%的代码都在设置操场页面和视图等。。。

    https://gist.github.com/oliver-foggin/7ef9e2b7f77b733ea0afb782d7c7d7e0

    总共花了我大约10分钟。

    看着你的动画,我注意到只有三件事在改变。圆形视图的大小、圆形视图的角半径和布局的轴(垂直/水平)。

    这反映在我的示例中使用的动画代码中。。。

    UIView.animate(withDuration: 0.5) {
        stackView.axis = .horizontal
        roundViewHeightConstraint.constant = 60
        roundView.layer.cornerRadius = 30
    }
    

    这将产生以下动画(可以对其进行调整以改进,但我没有太多时间来编写此动画)。。。

    enter image description here

    stackView.axis = .horizontal
    roundViewHeightConstraint.constant = 60
    
    UIView.animate(withDuration: 0.5) {
        containerView.layoutIfNeeded()
    }
    

    新建动画。。。 enter image description here