iOS动画– UIScrollView内的UIStackView
之前,我们已经通过示例进行了讨论并实现了UIStackView。
在本教程中,我们将学习如何在UIScrollView内添加UIStackView以及如何以编程方式实现从UIStackView添加和删除视图以及对其进行动画处理。
UIScrollView内的UIStackView
以下是您需要执行的步骤,以便在UIScrollView中添加UIStackView。
将UIScrollView添加到视图控制器视图,并将约束设置到视图的所有侧面。
在UIScrollView内添加一个UIStackView。
设置约束:ScrollView的前导,尾随,顶部和底部。如果要垂直滚动StackView,请在UIStackView和UIScrollView之间设置等宽约束。
如果要水平滚动StackView,请在UIStackView和UIScrollView之间设置等高约束。
在UIStackView内添加您的SubView,并享受滚动。
让我们在XCode项目Main.storyboard
中进行演示。
现在,我们在StackView中添加一些按钮:
模拟器中的输出如下:
接下来,让我们来看一下以编程方式构建UIStackView的过程。
UIStackView以编程方式
打开您的ViewController.swift文件,并添加以下代码行:
import UIKit class ViewController: UIViewController { var stackView = UIStackView() var constraintBottom : NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() //Do any additional setup after loading the view, typically from a nib. let textField = UITextField() textField.placeholder = "Email" textField.textColor = UIColor.darkGray textField.minimumFontSize = 17.0 textField.borderStyle = UITextField.BorderStyle.roundedRect textField.keyboardType = UIKeyboardType.emailAddress textField.returnKeyType = UIReturnKeyType.next let textFieldPassword = UITextField() textFieldPassword.placeholder = "Password" textFieldPassword.textColor = UIColor.darkGray textFieldPassword.minimumFontSize = 17.0 textFieldPassword.textAlignment = .right textFieldPassword.isSecureTextEntry = true textFieldPassword.borderStyle = UITextField.BorderStyle.roundedRect textFieldPassword.keyboardType = UIKeyboardType.default textFieldPassword.returnKeyType = UIReturnKeyType.done let button = UIButton(type: UIButton.ButtonType.system) button.setTitle("Login", for: UIControl.State.normal) button.setTitleColor(UIColor.white, for: UIControl.State.normal) button.backgroundColor = UIColor.black button.layer.borderColor = UIColor.white.cgColor button.layer.borderWidth = 1.0 button.layer.cornerRadius = 5.0 button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside) button.tag = 1 stackView = UIStackView(arrangedSubviews: [textField, textFieldPassword, button]) stackView.axis = .vertical stackView.translatesAutoresizingMaskIntoConstraints = false stackView.distribution = .fillEqually stackView.alignment = .fill stackView.spacing = 20.0 view.addSubview(stackView) stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true constraintBottom = stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40) constraintBottom?.isActive = true } @objc func buttonAction(sender: UIButton!) { if(sender.tag == 1){ constraintBottom?.isActive = false stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100).isActive = true } } }
在这段代码中,我们在UIStackView中垂直设置了UITextField和Button,它们均等填充。
我们使用NSLayoutConstraint在stackView上设置约束。
子视图在ArrangeSubView数组中传递。
单击"按钮"时,我们设置了一个选择器以禁用StackView的底部约束,并添加一个新的选择器以增加底部边距。
由于UIStackViews使用自动布局,因此必须将" translatesAutoresizingMaskIntoConstraints"设置为false。
isHidden属性用于切换完整StackView(包括其所有元素)的可见性。
使用功能加载子视图
我们可以使用如下所示的函数填充UIStackView,而不是在数组中传递单个subView:
class ViewController: UIViewController { var stackView = UIStackView() var constraintBottom : NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() //Do any additional setup after loading the view, typically from a nib. stackView = UIStackView(arrangedSubviews: createButtonArray(named: "1","2","3","4")) stackView.axis = .vertical stackView.translatesAutoresizingMaskIntoConstraints = false stackView.distribution = .fillEqually stackView.alignment = .fill stackView.spacing = 20.0 view.addSubview(stackView) stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true constraintBottom = stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40) constraintBottom?.isActive = true } func createButtonArray(named: String...) -> [UIButton] { return named.map{name in let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle("Button \(name)", for: .normal) button.backgroundColor = UIColor.red button.setTitleColor(UIColor.white, for: .normal) return button } } }
createButtonArray通过将字符串转换为相应的Button实例来组成数组,从而创建一个数组。
单击添加子视图
我们将上述每个按钮配置为在单击按钮时添加另一个subView。
我们将添加一个嵌套的子视图。
viewDidLoad方法与以前相同。
ViewController.swift中的其他方法是:
func createButtonArray(named: String...) -> [UIButton] { return named.map{name in let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle("Button \(name)", for: .normal) button.backgroundColor = UIColor.red button.setTitleColor(UIColor.white, for: .normal) button.tag = named.firstIndex(of: name)! button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside) return button } } @objc func buttonAction(sender: UIButton!) { print("Button tag is") print(sender.tag) createNestedSubView(sender.tag) } func createNestedSubView(_ tag: Int) { let ss = UIStackView(arrangedSubviews: createButtonArray(named: "\(tag+1).1","\(tag+1).2","\(tag+1).3","\(tag+1).4")) ss.axis = .horizontal ss.translatesAutoresizingMaskIntoConstraints = false ss.distribution = .fillEqually ss.alignment = .fill ss.spacing = 5.0 stackView.insertArrangedSubview(ss, at: tag) ss.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true ss.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true ss.heightAnchor.constraint(equalToConstant: 50.0).isActive = true }
因此,在单击按钮时,我们传递按钮的索引。
创建一个嵌套的水平StackView。
新的堆栈视图将插入标签编号索引处。
insertArrangedSubview
用于将SubView插入到UIStackView中的某个索引处。
ArrangeSubView用于在UIStackView的末尾插入新的SubView。
以编程方式删除SubView
我们可以使用UIStackView实例上的removeArrangedSubview函数删除SubView。
另外,我们也需要从SuperView中删除该视图。
在ViewController.swift createButtonArray函数中,我们为嵌套的StackView按钮添加了另一个按钮单击动作。
单击它们中的任何一个时,它们将被删除:
func createButtonArray(named: String...) -> [UIButton] { return named.map{name in let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle("Button \(name)", for: .normal) button.backgroundColor = UIColor.red button.setTitleColor(UIColor.white, for: .normal) button.tag = named.firstIndex(of: name)! if(name.contains(".")) { button.addTarget(self, action: #selector(deleteAction), for: .touchUpInside) } else{ button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside) } return button } } @objc func deleteAction(sender: UIButton!) { print("Delete tag is") print(sender.titleLabel?.text! ?? "NA") stackView.removeArrangedSubview(sender) sender.removeFromSuperview() }
动画子视图
当使用以下方法切换isHidden属性时,我们可以为subViews设置动画:
UIView.animate(withDuration: 0.5){ button.isHidden = true //or false }
在上面的应用程序中,当单击按钮4时,我们将其隐藏并设置动画:
@objc func buttonAction(sender: UIButton!) { print("Button tag is") print(sender.tag) if(sender.titleLabel?.text?.contains("4"))! { UIView.animate(withDuration: 0.5){ sender.isHidden = true //or false } } createNestedSubView(sender.tag) }