对全屏UIView的大小进行动画处理,以在屏幕底部显示另一个UIView

时间:2019-06-21 14:54:36

标签: ios swift uiview uiviewanimation

我正在更新一个iOS Swift应用程序(由他人创建),该应用程序包含一个最初填充整个屏幕的视图(“ View A”)。对于它的价值,该视图是一张地图。当用户点击地图上的兴趣点时,地图视图(“视图A”)的高度缩小到屏幕高度的75%,而另一视图(“视图B”)显示在底部25屏幕的百分比。这是该场景的直观描述。

enter image description here

目前,这是通过以下方式完成的:

// this is "View A"
var mapView: MGLMapView!
// this is "View B"
var pageViewController : UIPageViewController!
var pageViewControllerFrame = CGRect()

override func viewDidLoad() {
    super.viewDidLoad()

    // setup map view
    mapView = MGLMapView(frame: view.bounds, styleURL: styleUrl)
    mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    view.addSubview(mapView)

    // setup UIPageViewController
    pageViewControllerFrame = CGRect(x: 0, y: self.view.bounds.height * 0.75, width: mapView.bounds.width, height: self.view.bounds.height / 4)

    pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    pageViewController.view.frame = pageViewControllerFrame
    pageViewController.view.autoresizingMask = [.flexibleWidth]
    pageViewController.view.translatesAutoresizingMaskIntoConstraints = true
    view.addSubview(pageViewController.view)
    pageViewController.view.isHidden = true
}

@objc func handleMapTap(sender: UITapGestureRecognizer) {

    if userTappedOnPoi == true {
        self.mapView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height * 3/4)
        pageViewController.view.isHidden = false
    } else {
        // user tapped on the map but not on a POI so hide pageViewController and reset map frame to take up the entire screen
        pageViewController.view.isHidden = true
        mapView.frame = view.bounds
    }
}

如您所见,地图视图上有一个轻击手势识别器。如果用户点击POI,则将调整地图视图的框架,使高度为视图高度的75%,然后使底部视图(“视图B”)可见。这是可行的,但我认为如果对其进行动画处理会更好,因为地图视图的高度在缩小,底部的视图在屏幕上向上滑动。

我一直在玩animate(withDuration:delay:options:animations:completion:),但到目前为止,让动画正常工作还没有任何运气。我尝试过的大多数操作(即使持续时间约为3.0秒)似乎仍然会导致地图视图立即更改其高度。我猜这可能是因为没有自动布局约束来进行动画处理?

2 个答案:

答案 0 :(得分:1)

在您的情况下,使用自动布局会更好,因为分页器pageViewController.view.isHidden = true/false可以立即隐藏/显示,并且不会与地图的崩溃保持同步,因此请设置约束,例如

  

Mapview:顶部,前导,尾随和乘数高度

     

寻呼机:从顶部到地图,从顶部到底部,从底部到视图

然后动画化地图的高度倍增器的变化

var heightCon:NSLayoutConstraint!

heightCon.constant = self.view.bounds.height * 0.75
UIView.animate(withDuration: 0.5) {
  self.view.layoutIfNeeded()
}

答案 1 :(得分:1)

您还可以使用UIStackView,因此可以通过更改isHidden属性轻松获得动画。

示例:

import UIKit
import PlaygroundSupport

class VC: UIViewController {

    private let view1 = UIView()
    private let view2 = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view1.backgroundColor = .red
        view2.backgroundColor = .green
        view2.isHidden = true
        let stackView = UIStackView(arrangedSubviews: [view1, view2])
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        view.addSubview(stackView)
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            stackView.topAnchor.constraint(equalTo: view.topAnchor),
            stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            view2.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.25)
        ])
        view1.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:))))
    }

    @objc func handleMapTap(sender: Any) {
        UIView.animate(withDuration: 0.3) {
            self.view2.isHidden = !self.view2.isHidden
            self.view.layoutIfNeeded()
        }
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = VC()