动画调整全屏 UIView 的大小以在屏幕底部显示另一个 UIView
Animate the resizing of full screen UIView to show another UIView at bottom of screen
我正在更新一个 iOS Swift 应用程序(其他人创建的),其中包含一个最初填满整个屏幕的视图 ("View A")。就其价值而言,此视图是一张地图。当用户点击地图上的兴趣点时,地图视图的高度 ("View A") 会缩小到屏幕高度的 75%,并且另一个视图 ("View B") 会显示在屏幕底部 25%。这是该场景的直观描述。
目前是这样实现的:
// 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%,然后底部视图 ("View B") 可见。这是有效的,但我认为如果它是动画的看起来会更好,因为地图视图的高度正在缩小,底部的视图正在向上滑动到屏幕上。
我一直在玩 animate(withDuration:delay:options:animations:completion:)
,但到目前为止还没有运气让动画正常工作。我尝试过的大多数事情(即使持续时间约为 3.0 秒)似乎仍然会导致地图视图立即改变其高度。我猜这可能是因为没有设置动画的自动布局约束?
在你的情况下使用 auto-layout 更好,因为使用寻呼机 pageViewController.view.isHidden = true/false
是 hidden/shown 即时并且不同步到地图的折叠,所以设置约束
Mapview : top , leading , trailing and multiplier height
pager : top to map , leading , trailing and bottom to view
然后为地图的高度乘数的变化设置动画,例如
var heightCon:NSLayoutConstraint!
heightCon.constant = self.view.bounds.height * 0.75
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
您也可以使用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()
我正在更新一个 iOS Swift 应用程序(其他人创建的),其中包含一个最初填满整个屏幕的视图 ("View A")。就其价值而言,此视图是一张地图。当用户点击地图上的兴趣点时,地图视图的高度 ("View A") 会缩小到屏幕高度的 75%,并且另一个视图 ("View B") 会显示在屏幕底部 25%。这是该场景的直观描述。
目前是这样实现的:
// 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%,然后底部视图 ("View B") 可见。这是有效的,但我认为如果它是动画的看起来会更好,因为地图视图的高度正在缩小,底部的视图正在向上滑动到屏幕上。
我一直在玩 animate(withDuration:delay:options:animations:completion:)
,但到目前为止还没有运气让动画正常工作。我尝试过的大多数事情(即使持续时间约为 3.0 秒)似乎仍然会导致地图视图立即改变其高度。我猜这可能是因为没有设置动画的自动布局约束?
在你的情况下使用 auto-layout 更好,因为使用寻呼机 pageViewController.view.isHidden = true/false
是 hidden/shown 即时并且不同步到地图的折叠,所以设置约束
Mapview : top , leading , trailing and multiplier height
pager : top to map , leading , trailing and bottom to view
然后为地图的高度乘数的变化设置动画,例如
var heightCon:NSLayoutConstraint!
heightCon.constant = self.view.bounds.height * 0.75
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
您也可以使用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()