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)
}

