简体   繁体   English

如何为视图设置动画以隐藏在导航栏后面

[英]How to animate a view to hide behind Navigation Bar

I'm trying to animate a view to hide behind the navigation bar.我正在尝试为视图设置动画以隐藏在导航栏后面。 The idea is the yellow label to appear from behind the green view.这个想法是黄色 label 从绿色视图后面出现。

在此处输入图像描述

I tried this modifying the top constraint to a negative number, but it works but if the yellow view is bigger than the green one it ends over the safe area.我试过将顶部约束修改为负数,但它有效,但如果黄色视图大于绿色视图,它就会在安全区域结束。

My code:我的代码:

@IBAction func buttonClick(_ sender: Any) {
    UIView.animate(withDuration: 0.5) {
        if(self.topMargin.constant<0){
            self.topMargin.constant=0
        }else {
            self.topMargin.constant = -100
        }
        self.view.layoutIfNeeded()
    }
}

Thats the result when hidden:这就是隐藏时的结果:

在此处输入图像描述

How can I achieve this effect without invading the safe zone?如何在不侵入安全区的情况下实现这种效果?

setup your label under your Controller class:在您的 Controller class 下设置您的 label:

let myLabel: UILabel = {
    
    let label = UILabel()
    label.text = "Label"
    label.backgroundColor = .darkYellow
    label.textAlignment = .center
    label.textColor = .black
    label.font = .systemFont(ofSize: 16, weight: .semibold)
    label.translatesAutoresizingMaskIntoConstraints = false
    
    return label
}()

After that set two variables for label animation state:之后为 label animation state 设置两个变量:

var labelUp: NSLayoutConstraint!
var labeldown: NSLayoutConstraint!

In viewDidLoad setup your nav bar (I set it with my extension), present your label and constraints:在 viewDidLoad 中设置你的导航栏(我用我的扩展设置它),展示你的 label 和约束:

navigationItem.leftBarButtonItem = UIBarButtonItem(title: "label UP", style: .plain, target: self, action: #selector(self.handleAnimate))
    
    view.addSubview(myLabel)
    labeldown = myLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
    labeldown.isActive = true
    
    labelUp = myLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
    
    myLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    myLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    myLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

Now add a variable to control state of label and animation func:现在添加一个变量来控制label和animation func的state:

var controlStatusLabel = true

@objc fileprivate func handleAnimate() {
    
    switch controlStatusLabel {
    case true:
        UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "label Down", style: .plain, target: self, action: #selector(self.handleAnimate))
            self.labeldown.isActive = false
            self.labelUp.isActive = true
            self.view.layoutIfNeeded()
            self.controlStatusLabel = false
        }, completion: nil)
    default:
        UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "label UP", style: .plain, target: self, action: #selector(self.handleAnimate))
            self.labelUp.isActive = false
            self.labeldown.isActive = true
            self.view.layoutIfNeeded()
            self.controlStatusLabel = true
        }, completion: nil)
    }
}

The result:结果:

在此处输入图像描述

Embed your label (or whatever view you want to animate) in a "holder" view, constrained to the safe-area, with .clipsToBounds = true ...将您的 label(或您想要设置动画的任何视图)嵌入到“holder”视图中,限制在安全区域,使用.clipsToBounds = true ...

在此处输入图像描述

The holder view background will normally be clear -- I'm toggling it between clear and red so you can see it's frame.支架视图背景通常是清晰的——我在透明和红色之间切换,这样你就可以看到它的框架。

Here'a quick example code for that:这是一个快速示例代码:

class ViewController: UIViewController {

    let label = UILabel()
    let labelHolderView = UIView()
    
    var labelTop: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.title = "Nav Bar"

        // configure the label
        label.textAlignment = .center
        label.text = "I'm going to slide up."
        label.backgroundColor = .systemYellow
        
        // add it to the holder view
        labelHolderView.addSubview(label)
        
        // prevents label from showing outside the bounds
        labelHolderView.clipsToBounds = true

        label.translatesAutoresizingMaskIntoConstraints = false
        labelHolderView.translatesAutoresizingMaskIntoConstraints = false

        // add holder view to self.view
        view.addSubview(labelHolderView)

        // constant height for the label
        let labelHeight: CGFloat = 160.0
        
        // setup label top constraint
        labelTop = label.topAnchor.constraint(equalTo: labelHolderView.topAnchor)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([

            // activate label top constraint
            labelTop,
            
            // constrain label Leading/Trailing to holder
            //  we'll inset it by 20-points so we can see the holder view
            label.leadingAnchor.constraint(equalTo: labelHolderView.leadingAnchor, constant: 20.0),
            label.trailingAnchor.constraint(equalTo: labelHolderView.trailingAnchor, constant: -20.0),
            
            // constant height
            label.heightAnchor.constraint(equalToConstant: labelHeight),
            
            // label gets NO Bottom constraint
            
            // constrain holder to safe area
            labelHolderView.topAnchor.constraint(equalTo: g.topAnchor),
            labelHolderView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            labelHolderView.trailingAnchor.constraint(equalTo: g.trailingAnchor),

            // constant height (same as label height)
            labelHolderView.heightAnchor.constraint(equalTo: label.heightAnchor),
            
        ])
        
        // let's add a button to animate the label
        //  and one to show/hide the holder view
        let btn1 = UIButton(type: .system)
        btn1.setTitle("Animate It", for: [])
        btn1.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(btn1)
        
        let btn2 = UIButton(type: .system)
        btn2.setTitle("Toggle Holder View Color", for: [])
        btn2.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(btn2)

        NSLayoutConstraint.activate([
            // put the first button below the holder view
            btn1.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn1.topAnchor.constraint(equalTo: labelHolderView.bottomAnchor, constant: 20.0),
            // second button below it
            btn2.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn2.topAnchor.constraint(equalTo: btn1.bottomAnchor, constant: 20.0),

        ])
        

        // give the buttons an action
        btn1.addTarget(self, action: #selector(animLabel(_:)), for: .touchUpInside)
        btn2.addTarget(self, action: #selector(toggleHolderColor(_:)), for: .touchUpInside)

    }
    
    @objc func animLabel(_ sender: Any?) {
        // animate the label up if it's down, down if it's up
        labelTop.constant = labelTop.constant == 0 ? -label.frame.height : 0
        UIView.animate(withDuration: 0.5, animations: {
            self.view.layoutIfNeeded()
        })
    }
    
    @objc func toggleHolderColor(_ sender: Any?) {
        labelHolderView.backgroundColor = labelHolderView.backgroundColor == .red ? .clear : .red
    }
    
}

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

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