UIStackView show/hide 动画
UIStackView show/hide animation
在堆栈视图中,我有 UIPickerView,我想在点击按钮时折叠和展开它。我想使用一个简单的动画,但不知道如何实现,我尝试了很多方法,但 none 导致正确的外观我总是得到这个
我想让选择器也折叠起来,但它没有。它只是在动画之后才消失,看起来不太好看。
我的代码,其中 self 是 UIStackView:
UIView.animate(withDuration: 0.3, animations: { [unowned self] in
self.picker.isHidden = !open
self.layoutIfNeeded()
})
堆栈视图的自动 show/hide 动画效果很好 --- 对于 一些 东西。对于其他人,例如选择器视图,则没有那么多(如您所见)。
一种方法是:
- 在常规视图中嵌入选择器视图
- 限制它垂直居中
- 向包含视图添加默认高度(例如比选择器视图略高)
- 为视图的高度约束设置动画
选择器视图不会 "squeeze" 自己,所以你会得到一个 "disappearing" 选择器视图。如果你想让它在动画时"squeeze",你还需要动画它的变换
这是一个例子(我使用对比色使元素更容易看清,并且我放慢了动画持续时间以使其明显):
示例代码如下:
class StackDemoViewController: UIViewController {
@IBOutlet var pickerHolderView: UIView!
@IBOutlet var pickerHolderHeightConstraint: NSLayoutConstraint!
@IBOutlet var normalButton: UIButton!
@IBOutlet var squeezeButton: UIButton!
@IBOutlet var thePickerView: UIDatePicker!
// this will be assigned in viewDidLoad
var defaultPickerHolderViewHeight: CGFloat = 0.0
// anim duration - change to something like 1.0 to see the effect in "slo-motion"
let animDuration = 0.3
override func viewDidLoad() {
super.viewDidLoad()
// get the original picker holder view height constant
defaultPickerHolderViewHeight = pickerHolderHeightConstraint.constant
}
@IBAction func normalAnim(_ sender: Any) {
// local bool
let bIsHidden = pickerHolderView.isHidden
// if the picker holder view is currently hidden, show it
if bIsHidden {
pickerHolderView.isHidden = false
}
// if picker holder height constant is > 0 (it's open / showing)
// set it to 0
// else
// set it to defaultPickerHolderViewHeight
self.pickerHolderHeightConstraint.constant = self.pickerHolderHeightConstraint.constant > 0 ? 0 : defaultPickerHolderViewHeight
// animate the change
UIView.animate(withDuration: animDuration, animations: {
self.view.layoutIfNeeded()
}) { finished in
// if the picker holder view was showing (NOT hidden)
// hide it
if !bIsHidden {
self.pickerHolderView.isHidden = true
// disable squeeze button until view is showing again
self.squeezeButton.isEnabled = false
} else {
// re-enable squeeze button
self.squeezeButton.isEnabled = true
}
}
}
@IBAction func squeezeAnim(_ sender: Any) {
// local bool
let bIsHidden = pickerHolderView.isHidden
var t = CGAffineTransform.identity
// if the picker holder view is currently hidden, show it
if bIsHidden {
pickerHolderView.isHidden = false
} else {
// we're going to hide it
t = CGAffineTransform(scaleX: 1.0, y: 0.01)
}
// if picker holder height constant is > 0 (it's open / showing)
// set it to 0
// else
// set it to defaultPickerHolderViewHeight
self.pickerHolderHeightConstraint.constant = self.pickerHolderHeightConstraint.constant > 0 ? 0 : defaultPickerHolderViewHeight
// animate the change
UIView.animate(withDuration: animDuration, animations: {
self.thePickerView.transform = t
self.view.layoutIfNeeded()
}) { finished in
// if the picker holder view was showing (NOT hidden)
// hide it
if !bIsHidden {
self.pickerHolderView.isHidden = true
// disable normal button until view is showing again
self.normalButton.isEnabled = false
} else {
// re-enable normal button
self.normalButton.isEnabled = true
}
}
}
}
使用此布局:
并且,这是情节提要的来源(因此您可以自己快速尝试一下):
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Zg0-f1-bBK">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Stack Demo View Controller-->
<scene sceneID="Itw-fL-6gO">
<objects>
<viewController id="Zg0-f1-bBK" customClass="StackDemoViewController" customModule="TranslateTest" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="rze-A8-JnC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="vDP-gh-oah">
<rect key="frame" x="8" y="120" width="359" height="338"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="clh-vv-1e4">
<rect key="frame" x="0.0" y="0.0" width="359" height="50"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="VMQ-JX-yNt">
<rect key="frame" x="8" y="8" width="343" height="34"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zb9-rN-qPb">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="34"/>
<color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Normal"/>
<connections>
<action selector="normalAnim:" destination="Zg0-f1-bBK" eventType="touchUpInside" id="zwU-Bs-ZlI"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v2b-2E-upp">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="34"/>
<color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="With Squeeze"/>
<connections>
<action selector="squeezeAnim:" destination="Zg0-f1-bBK" eventType="touchUpInside" id="ARc-fQ-XRE"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="VMQ-JX-yNt" secondAttribute="trailing" constant="8" id="T0v-du-5Aj"/>
<constraint firstItem="VMQ-JX-yNt" firstAttribute="top" secondItem="clh-vv-1e4" secondAttribute="top" constant="8" id="Y2j-KP-ylE"/>
<constraint firstItem="VMQ-JX-yNt" firstAttribute="leading" secondItem="clh-vv-1e4" secondAttribute="leading" constant="8" id="mKK-5Q-IhS"/>
<constraint firstAttribute="bottom" secondItem="VMQ-JX-yNt" secondAttribute="bottom" constant="8" id="uJf-Y8-Uun"/>
</constraints>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6L1-Bv-SxB">
<rect key="frame" x="0.0" y="58" width="359" height="232"/>
<subviews>
<datePicker contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" datePickerMode="dateAndTime" minuteInterval="1" translatesAutoresizingMaskIntoConstraints="NO" id="0A6-0Z-m7u">
<rect key="frame" x="8" y="8" width="343" height="216"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<date key="date" timeIntervalSinceReferenceDate="590598642.83352995">
<!--2019-09-19 15:10:42 +0000-->
</date>
</datePicker>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="0A6-0Z-m7u" firstAttribute="centerY" secondItem="6L1-Bv-SxB" secondAttribute="centerY" id="Eqi-Od-JBH"/>
<constraint firstItem="0A6-0Z-m7u" firstAttribute="leading" secondItem="6L1-Bv-SxB" secondAttribute="leading" constant="8" id="IEp-7K-buG"/>
<constraint firstAttribute="height" constant="232" id="e1y-wA-jqj"/>
<constraint firstAttribute="trailing" secondItem="0A6-0Z-m7u" secondAttribute="trailing" constant="8" id="hLe-WM-Qnx"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Standard UILabel" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X5m-RD-zx4">
<rect key="frame" x="0.0" y="298" width="359" height="40"/>
<color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="4c2-X0-9Kb"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="0.52747867609999999" green="1" blue="0.55622484120000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="k9S-Qf-yG1" firstAttribute="trailing" secondItem="vDP-gh-oah" secondAttribute="trailing" constant="8" id="5C9-Ef-syQ"/>
<constraint firstItem="vDP-gh-oah" firstAttribute="top" secondItem="k9S-Qf-yG1" secondAttribute="top" constant="100" id="cuG-HE-aDz"/>
<constraint firstItem="vDP-gh-oah" firstAttribute="leading" secondItem="rze-A8-JnC" secondAttribute="leading" constant="8" id="f5f-qW-BJ2"/>
</constraints>
<viewLayoutGuide key="safeArea" id="k9S-Qf-yG1"/>
</view>
<connections>
<outlet property="normalButton" destination="Zb9-rN-qPb" id="0sr-a2-wa9"/>
<outlet property="pickerHolderHeightConstraint" destination="e1y-wA-jqj" id="t7m-zQ-RwA"/>
<outlet property="pickerHolderView" destination="6L1-Bv-SxB" id="hkf-zy-GIS"/>
<outlet property="squeezeButton" destination="v2b-2E-upp" id="fFe-hm-qzd"/>
<outlet property="thePickerView" destination="0A6-0Z-m7u" id="ubt-fR-mx9"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="e1N-yd-USh" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2244" y="126.38680659670166"/>
</scene>
</scenes>
</document>
您可以将usingSpringWithDamping
与动画代码一起使用
Swift5:向上滑动动画
1- 将高度设置为 216(PickerView 标准)。
2- 设置尾随到安全区域。
3- 将底部设置为“SuperViewBottom”,如 -216。
4- 从第 3 行创建一个 IBOutlet 作为 NSLayoutConstraint 可选。
然后:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var bottom: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
bottom.constant = -216
}
-(IBAction)button:(id)sender
{
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations:
{
self.bottom.constant = 0
self.view.layoutIfNeeded()
}) { (AnimationComplete ) in }
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations:
{
self.bottom.constant = -216
self.view.layoutIfNeeded()
}) { (AnimationComplete ) in }
}
}
它应该像 Apple 标准动画一样工作。
祝你好运
在堆栈视图中,我有 UIPickerView,我想在点击按钮时折叠和展开它。我想使用一个简单的动画,但不知道如何实现,我尝试了很多方法,但 none 导致正确的外观我总是得到这个
我想让选择器也折叠起来,但它没有。它只是在动画之后才消失,看起来不太好看。
我的代码,其中 self 是 UIStackView:
UIView.animate(withDuration: 0.3, animations: { [unowned self] in
self.picker.isHidden = !open
self.layoutIfNeeded()
})
堆栈视图的自动 show/hide 动画效果很好 --- 对于 一些 东西。对于其他人,例如选择器视图,则没有那么多(如您所见)。
一种方法是:
- 在常规视图中嵌入选择器视图
- 限制它垂直居中
- 向包含视图添加默认高度(例如比选择器视图略高)
- 为视图的高度约束设置动画
选择器视图不会 "squeeze" 自己,所以你会得到一个 "disappearing" 选择器视图。如果你想让它在动画时"squeeze",你还需要动画它的变换
这是一个例子(我使用对比色使元素更容易看清,并且我放慢了动画持续时间以使其明显):
示例代码如下:
class StackDemoViewController: UIViewController {
@IBOutlet var pickerHolderView: UIView!
@IBOutlet var pickerHolderHeightConstraint: NSLayoutConstraint!
@IBOutlet var normalButton: UIButton!
@IBOutlet var squeezeButton: UIButton!
@IBOutlet var thePickerView: UIDatePicker!
// this will be assigned in viewDidLoad
var defaultPickerHolderViewHeight: CGFloat = 0.0
// anim duration - change to something like 1.0 to see the effect in "slo-motion"
let animDuration = 0.3
override func viewDidLoad() {
super.viewDidLoad()
// get the original picker holder view height constant
defaultPickerHolderViewHeight = pickerHolderHeightConstraint.constant
}
@IBAction func normalAnim(_ sender: Any) {
// local bool
let bIsHidden = pickerHolderView.isHidden
// if the picker holder view is currently hidden, show it
if bIsHidden {
pickerHolderView.isHidden = false
}
// if picker holder height constant is > 0 (it's open / showing)
// set it to 0
// else
// set it to defaultPickerHolderViewHeight
self.pickerHolderHeightConstraint.constant = self.pickerHolderHeightConstraint.constant > 0 ? 0 : defaultPickerHolderViewHeight
// animate the change
UIView.animate(withDuration: animDuration, animations: {
self.view.layoutIfNeeded()
}) { finished in
// if the picker holder view was showing (NOT hidden)
// hide it
if !bIsHidden {
self.pickerHolderView.isHidden = true
// disable squeeze button until view is showing again
self.squeezeButton.isEnabled = false
} else {
// re-enable squeeze button
self.squeezeButton.isEnabled = true
}
}
}
@IBAction func squeezeAnim(_ sender: Any) {
// local bool
let bIsHidden = pickerHolderView.isHidden
var t = CGAffineTransform.identity
// if the picker holder view is currently hidden, show it
if bIsHidden {
pickerHolderView.isHidden = false
} else {
// we're going to hide it
t = CGAffineTransform(scaleX: 1.0, y: 0.01)
}
// if picker holder height constant is > 0 (it's open / showing)
// set it to 0
// else
// set it to defaultPickerHolderViewHeight
self.pickerHolderHeightConstraint.constant = self.pickerHolderHeightConstraint.constant > 0 ? 0 : defaultPickerHolderViewHeight
// animate the change
UIView.animate(withDuration: animDuration, animations: {
self.thePickerView.transform = t
self.view.layoutIfNeeded()
}) { finished in
// if the picker holder view was showing (NOT hidden)
// hide it
if !bIsHidden {
self.pickerHolderView.isHidden = true
// disable normal button until view is showing again
self.normalButton.isEnabled = false
} else {
// re-enable normal button
self.normalButton.isEnabled = true
}
}
}
}
使用此布局:
并且,这是情节提要的来源(因此您可以自己快速尝试一下):
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Zg0-f1-bBK">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Stack Demo View Controller-->
<scene sceneID="Itw-fL-6gO">
<objects>
<viewController id="Zg0-f1-bBK" customClass="StackDemoViewController" customModule="TranslateTest" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="rze-A8-JnC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="vDP-gh-oah">
<rect key="frame" x="8" y="120" width="359" height="338"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="clh-vv-1e4">
<rect key="frame" x="0.0" y="0.0" width="359" height="50"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="VMQ-JX-yNt">
<rect key="frame" x="8" y="8" width="343" height="34"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zb9-rN-qPb">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="34"/>
<color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Normal"/>
<connections>
<action selector="normalAnim:" destination="Zg0-f1-bBK" eventType="touchUpInside" id="zwU-Bs-ZlI"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v2b-2E-upp">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="34"/>
<color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="With Squeeze"/>
<connections>
<action selector="squeezeAnim:" destination="Zg0-f1-bBK" eventType="touchUpInside" id="ARc-fQ-XRE"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="VMQ-JX-yNt" secondAttribute="trailing" constant="8" id="T0v-du-5Aj"/>
<constraint firstItem="VMQ-JX-yNt" firstAttribute="top" secondItem="clh-vv-1e4" secondAttribute="top" constant="8" id="Y2j-KP-ylE"/>
<constraint firstItem="VMQ-JX-yNt" firstAttribute="leading" secondItem="clh-vv-1e4" secondAttribute="leading" constant="8" id="mKK-5Q-IhS"/>
<constraint firstAttribute="bottom" secondItem="VMQ-JX-yNt" secondAttribute="bottom" constant="8" id="uJf-Y8-Uun"/>
</constraints>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6L1-Bv-SxB">
<rect key="frame" x="0.0" y="58" width="359" height="232"/>
<subviews>
<datePicker contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" datePickerMode="dateAndTime" minuteInterval="1" translatesAutoresizingMaskIntoConstraints="NO" id="0A6-0Z-m7u">
<rect key="frame" x="8" y="8" width="343" height="216"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<date key="date" timeIntervalSinceReferenceDate="590598642.83352995">
<!--2019-09-19 15:10:42 +0000-->
</date>
</datePicker>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="0A6-0Z-m7u" firstAttribute="centerY" secondItem="6L1-Bv-SxB" secondAttribute="centerY" id="Eqi-Od-JBH"/>
<constraint firstItem="0A6-0Z-m7u" firstAttribute="leading" secondItem="6L1-Bv-SxB" secondAttribute="leading" constant="8" id="IEp-7K-buG"/>
<constraint firstAttribute="height" constant="232" id="e1y-wA-jqj"/>
<constraint firstAttribute="trailing" secondItem="0A6-0Z-m7u" secondAttribute="trailing" constant="8" id="hLe-WM-Qnx"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Standard UILabel" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X5m-RD-zx4">
<rect key="frame" x="0.0" y="298" width="359" height="40"/>
<color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="4c2-X0-9Kb"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="0.52747867609999999" green="1" blue="0.55622484120000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="k9S-Qf-yG1" firstAttribute="trailing" secondItem="vDP-gh-oah" secondAttribute="trailing" constant="8" id="5C9-Ef-syQ"/>
<constraint firstItem="vDP-gh-oah" firstAttribute="top" secondItem="k9S-Qf-yG1" secondAttribute="top" constant="100" id="cuG-HE-aDz"/>
<constraint firstItem="vDP-gh-oah" firstAttribute="leading" secondItem="rze-A8-JnC" secondAttribute="leading" constant="8" id="f5f-qW-BJ2"/>
</constraints>
<viewLayoutGuide key="safeArea" id="k9S-Qf-yG1"/>
</view>
<connections>
<outlet property="normalButton" destination="Zb9-rN-qPb" id="0sr-a2-wa9"/>
<outlet property="pickerHolderHeightConstraint" destination="e1y-wA-jqj" id="t7m-zQ-RwA"/>
<outlet property="pickerHolderView" destination="6L1-Bv-SxB" id="hkf-zy-GIS"/>
<outlet property="squeezeButton" destination="v2b-2E-upp" id="fFe-hm-qzd"/>
<outlet property="thePickerView" destination="0A6-0Z-m7u" id="ubt-fR-mx9"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="e1N-yd-USh" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2244" y="126.38680659670166"/>
</scene>
</scenes>
</document>
您可以将usingSpringWithDamping
与动画代码一起使用
Swift5:向上滑动动画
1- 将高度设置为 216(PickerView 标准)。
2- 设置尾随到安全区域。
3- 将底部设置为“SuperViewBottom”,如 -216。
4- 从第 3 行创建一个 IBOutlet 作为 NSLayoutConstraint 可选。
然后:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var bottom: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
bottom.constant = -216
}
-(IBAction)button:(id)sender
{
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations:
{
self.bottom.constant = 0
self.view.layoutIfNeeded()
}) { (AnimationComplete ) in }
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations:
{
self.bottom.constant = -216
self.view.layoutIfNeeded()
}) { (AnimationComplete ) in }
}
}
它应该像 Apple 标准动画一样工作。
祝你好运