我正在尝试使一组图像视图从一个点动画化,例如扩展菜单的工作方式。该页面是用已经显示的按钮构建的,在viewDidLayoutSubviews()期间,我将它们动画化。当按下按钮时,我会将它们设置为原始位置的动画,所有动画均基于更改图像视图的中心。我遇到的问题是由于某种原因,动画输出向右偏移了一点。在大型设备上,这还不错,但在小型设备上,这是一个大问题。所有UI均使用autoLayout构建:
这是用于设置中心位置的代码,该代码在发生任何动画之前运行:
micContainerLocation = micContainer.center
cameraContainerLocation = cameraContainer.center
pencilContainerLocation = pencilContainer.center
calendarContainerLocation = calendarContainer.center
以下是动画按钮动画:
UIView.animate(withDuration: 0.3, animations: {
self.calendarContainer.center = self.calendarContainerLocation
self.cameraContainer.center = self.cameraContainerLocation
self.micContainer.center = self.micContainerLocation
self.pencilContainer.center = self.pencilContainerLocation
self.sendMessageButton.alpha = 0
self.openMenuButton.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 4))
})
结果是:
任何建议将不胜感激。谢谢。
编辑:
不确定是否有帮助,但这是自动布局中的有害对象的图片。
以及详细的约束列表:
答案 0 :(得分:1)
我怀疑问题(或问题的至少一部分)是将显式.center
值与自动布局约束混合在一起。还有可能您没有获得“真实的”中心值。
另一种方法,仅使用自动布局,是为“隐藏”位置创建约束数组,为“可见”位置创建约束数组。然后停用/激活以显示/隐藏按钮。
而且...比说起来容易:)
@IBOutlet
)。另一个优点是,即使超级视图的宽度发生了变化(例如在设备旋转时),按钮也将自动调整大小/位置,而无需任何代码来重新评估.center
属性。
这是情节提要约束条件占位符设置的图像:
基本思想是:
创建一组约束,以便按钮容器在左边缘的左侧不可见。那就是“隐藏的”约束。
创建一组约束,以便按钮容器在视图中,并且每个容器对齐/大小适当。那将是“可见的”约束。
这听起来似乎很复杂,但是如果您看下面的示例,我想您会发现实际上没有什么事。
此示例应按原样运行...只需创建一个新的Storyboard并替换源,然后使用以下类。它所拥有的并不是完全准确,但应该足够接近以至于可以作为起点。
代码如下:
//
// AnimButtonsViewController.swift
//
// Created by Don Mag on 3/15/19.
//
import UIKit
class AnimButtonsViewController: UIViewController {
@IBOutlet var pencilContainer: UIView!
@IBOutlet var cameraContainer: UIView!
@IBOutlet var micContainer: UIView!
@IBOutlet var calendarContainer: UIView!
@IBOutlet var buttonsContainer: UIView!
var hiddenConstraints = [NSLayoutConstraint]()
var visibleConstraints = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
var c = NSLayoutConstraint()
// set up the "hidden" constraints
// constrain pencilContainer (1) *trailing* to buttonsContainer *leading*
// this will place it outside the view (to the left of left edge)
c = pencilContainer.trailingAnchor.constraint(equalTo: buttonsContainer.leadingAnchor)
hiddenConstraints.append(c)
// constrain leading of remaining buttons to leading of pencilContainer
// they are now all "overlaid" on top of each other, outside the view
c = cameraContainer.leadingAnchor.constraint(equalTo: pencilContainer.leadingAnchor)
hiddenConstraints.append(c)
c = micContainer.leadingAnchor.constraint(equalTo: pencilContainer.leadingAnchor)
hiddenConstraints.append(c)
c = calendarContainer.leadingAnchor.constraint(equalTo: pencilContainer.leadingAnchor)
hiddenConstraints.append(c)
// set up the "visible" constraints
// constrain first button (pencilContainer (1)) *leading* to buttonsContainer *leading*
// and each remaining button constrain its leading to the previous button's trailing
c = pencilContainer.leadingAnchor.constraint(equalTo: buttonsContainer.leadingAnchor)
visibleConstraints.append(c)
c = cameraContainer.leadingAnchor.constraint(equalTo: pencilContainer.trailingAnchor)
visibleConstraints.append(c)
c = micContainer.leadingAnchor.constraint(equalTo: cameraContainer.trailingAnchor)
visibleConstraints.append(c)
c = calendarContainer.leadingAnchor.constraint(equalTo: micContainer.trailingAnchor)
visibleConstraints.append(c)
// contrain last button (calendarContainer (4)) trailing to buttonsContrainer trailing
c = calendarContainer.trailingAnchor.constraint(equalTo: buttonsContainer.trailingAnchor)
visibleConstraints.append(c)
// activate the hidden constraints
NSLayoutConstraint.activate(hiddenConstraints)
}
@IBAction func showHideTapped(_ sender: Any) {
if let b = sender as? UIButton {
// just for demo purposes,
// if the button title is "+" we need to "show" the buttons
// if the button title is "X" we need to "hide" the buttons
let t = b.currentTitle
if t == "+" {
NSLayoutConstraint.deactivate(hiddenConstraints)
NSLayoutConstraint.activate(visibleConstraints)
b.setTitle("X", for: .normal)
} else {
NSLayoutConstraint.deactivate(visibleConstraints)
NSLayoutConstraint.activate(hiddenConstraints)
b.setTitle("+", for: .normal)
}
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
}
}
}
这是情节提要的源代码:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Msu-cJ-7P1">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Anim Buttons View Controller-->
<scene sceneID="LEr-rD-3kQ">
<objects>
<viewController id="Msu-cJ-7P1" customClass="AnimButtonsViewController" customModule="XC10SWScratch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Efg-NM-r2G">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tXi-AX-zDz" userLabel="Red View">
<rect key="frame" x="30" y="278.5" width="315" height="110"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BDK-vE-tUk">
<rect key="frame" x="4" y="30" width="273" height="50"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EbR-gU-YBO">
<rect key="frame" x="0.0" y="0.0" width="68.5" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="unV-LI-1jJ">
<rect key="frame" x="14" y="5" width="40" height="40"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="F0Z-oi-HlI"/>
<constraint firstAttribute="width" constant="40" id="P3x-Ak-lZY"/>
</constraints>
<state key="normal" title="1"/>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="unV-LI-1jJ" firstAttribute="centerX" secondItem="EbR-gU-YBO" secondAttribute="centerX" id="ZEb-9h-WvV"/>
<constraint firstItem="unV-LI-1jJ" firstAttribute="centerY" secondItem="EbR-gU-YBO" secondAttribute="centerY" id="mB2-5w-Egs"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" secondItem="unV-LI-1jJ" secondAttribute="width" id="mYy-gx-PT4"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QjG-7X-1Sa">
<rect key="frame" x="68.5" y="0.0" width="68" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qYS-Qj-f9n">
<rect key="frame" x="14" y="5" width="40" height="40"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="To5-l0-frk"/>
<constraint firstAttribute="width" constant="40" id="m9L-d5-Mac"/>
</constraints>
<state key="normal" title="2"/>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="qYS-Qj-f9n" firstAttribute="centerX" secondItem="QjG-7X-1Sa" secondAttribute="centerX" id="nNp-T0-rxc"/>
<constraint firstItem="qYS-Qj-f9n" firstAttribute="centerY" secondItem="QjG-7X-1Sa" secondAttribute="centerY" id="pDK-Y0-lag"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5IF-rt-c8a">
<rect key="frame" x="136.5" y="0.0" width="68.5" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="E15-8G-pOx">
<rect key="frame" x="14" y="5" width="40" height="40"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="ADz-st-xYC"/>
<constraint firstAttribute="width" constant="40" id="rIE-3o-Yih"/>
</constraints>
<state key="normal" title="3"/>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="E15-8G-pOx" firstAttribute="centerY" secondItem="5IF-rt-c8a" secondAttribute="centerY" id="NW3-qd-aRL"/>
<constraint firstItem="E15-8G-pOx" firstAttribute="centerX" secondItem="5IF-rt-c8a" secondAttribute="centerX" id="cyb-wZ-bhq"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kHB-hc-CY5">
<rect key="frame" x="205" y="0.0" width="68" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QrB-eG-9oo">
<rect key="frame" x="14" y="5" width="40" height="40"/>
<color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="4Qh-a1-bzP"/>
<constraint firstAttribute="height" constant="40" id="maJ-ei-IEH"/>
</constraints>
<state key="normal" title="4"/>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="QrB-eG-9oo" firstAttribute="centerX" secondItem="kHB-hc-CY5" secondAttribute="centerX" id="Enu-M7-oc0"/>
<constraint firstItem="QrB-eG-9oo" firstAttribute="centerY" secondItem="kHB-hc-CY5" secondAttribute="centerY" id="iwr-AG-t6j"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="kHB-hc-CY5" firstAttribute="centerY" secondItem="EbR-gU-YBO" secondAttribute="centerY" id="17U-hP-XiO"/>
<constraint firstItem="EbR-gU-YBO" firstAttribute="height" secondItem="BDK-vE-tUk" secondAttribute="height" id="2Kc-yZ-8EB"/>
<constraint firstItem="QjG-7X-1Sa" firstAttribute="width" secondItem="EbR-gU-YBO" secondAttribute="width" id="3bm-Ya-pZA"/>
<constraint firstItem="EbR-gU-YBO" firstAttribute="leading" secondItem="BDK-vE-tUk" secondAttribute="leading" placeholder="YES" id="6E3-jg-Ku3"/>
<constraint firstItem="EbR-gU-YBO" firstAttribute="centerY" secondItem="BDK-vE-tUk" secondAttribute="centerY" id="8hy-lM-jcp"/>
<constraint firstAttribute="trailing" secondItem="kHB-hc-CY5" secondAttribute="trailing" placeholder="YES" id="HQQ-As-qWL"/>
<constraint firstItem="QjG-7X-1Sa" firstAttribute="height" secondItem="EbR-gU-YBO" secondAttribute="height" id="HRx-Ud-bkP"/>
<constraint firstItem="5IF-rt-c8a" firstAttribute="height" secondItem="EbR-gU-YBO" secondAttribute="height" id="L5Q-Ee-ZSx"/>
<constraint firstItem="QjG-7X-1Sa" firstAttribute="leading" secondItem="EbR-gU-YBO" secondAttribute="trailing" placeholder="YES" id="NMH-3d-uhZ"/>
<constraint firstItem="5IF-rt-c8a" firstAttribute="centerY" secondItem="EbR-gU-YBO" secondAttribute="centerY" id="Nma-OU-J25"/>
<constraint firstItem="kHB-hc-CY5" firstAttribute="height" secondItem="EbR-gU-YBO" secondAttribute="height" id="WXs-c8-mbJ"/>
<constraint firstItem="kHB-hc-CY5" firstAttribute="width" secondItem="EbR-gU-YBO" secondAttribute="width" id="Y87-Ph-wOu"/>
<constraint firstAttribute="height" constant="50" id="YRG-m1-zQ0"/>
<constraint firstItem="5IF-rt-c8a" firstAttribute="leading" secondItem="QjG-7X-1Sa" secondAttribute="trailing" placeholder="YES" id="cTU-cd-6gQ"/>
<constraint firstItem="QjG-7X-1Sa" firstAttribute="centerY" secondItem="EbR-gU-YBO" secondAttribute="centerY" id="fd7-iE-WFg"/>
<constraint firstItem="5IF-rt-c8a" firstAttribute="width" secondItem="EbR-gU-YBO" secondAttribute="width" id="jAO-LF-jvX"/>
<constraint firstItem="kHB-hc-CY5" firstAttribute="leading" secondItem="5IF-rt-c8a" secondAttribute="trailing" placeholder="YES" id="kNi-xf-omT"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="smc-cM-nTo">
<rect key="frame" x="281" y="40" width="30" height="30"/>
<color key="backgroundColor" red="0.75406885150000003" green="0.75408679249999999" blue="0.75407713649999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="+">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="showHideTapped:" destination="Msu-cJ-7P1" eventType="touchUpInside" id="spY-Hq-Xeu"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="smc-cM-nTo" secondAttribute="trailing" constant="4" id="3Ry-gN-0Z4"/>
<constraint firstItem="smc-cM-nTo" firstAttribute="leading" secondItem="BDK-vE-tUk" secondAttribute="trailing" constant="4" id="I2C-fT-Op3"/>
<constraint firstItem="smc-cM-nTo" firstAttribute="centerY" secondItem="tXi-AX-zDz" secondAttribute="centerY" id="Mmb-uk-L5E"/>
<constraint firstItem="BDK-vE-tUk" firstAttribute="leading" secondItem="tXi-AX-zDz" secondAttribute="leading" constant="4" id="NXB-2K-Egb"/>
<constraint firstAttribute="height" constant="110" id="inu-kU-GH9"/>
<constraint firstItem="BDK-vE-tUk" firstAttribute="centerY" secondItem="tXi-AX-zDz" secondAttribute="centerY" id="kDF-XJ-qkj"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="tXi-AX-zDz" firstAttribute="leading" secondItem="12L-io-1Iw" secondAttribute="leading" constant="30" id="30d-ds-ZVg"/>
<constraint firstItem="12L-io-1Iw" firstAttribute="trailing" secondItem="tXi-AX-zDz" secondAttribute="trailing" constant="30" id="ofy-ZY-LjW"/>
<constraint firstItem="tXi-AX-zDz" firstAttribute="centerY" secondItem="Efg-NM-r2G" secondAttribute="centerY" id="rtS-1o-e1I"/>
</constraints>
<viewLayoutGuide key="safeArea" id="12L-io-1Iw"/>
</view>
<connections>
<outlet property="buttonsContainer" destination="BDK-vE-tUk" id="qkA-Rn-M8Z"/>
<outlet property="calendarContainer" destination="kHB-hc-CY5" id="red-ot-mmb"/>
<outlet property="cameraContainer" destination="QjG-7X-1Sa" id="P94-ES-YRb"/>
<outlet property="micContainer" destination="5IF-rt-c8a" id="ipp-Bt-B2m"/>
<outlet property="pencilContainer" destination="EbR-gU-YBO" id="Fr9-7f-BIa"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Y2G-rV-gCJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-478" y="2845"/>
</scene>
</scenes>
</document>
结果(点按灰色按钮将使按钮的进出动画):