简体   繁体   English

设置UIImageView动画时无法居中

[英]Centering a UIImageView not working while animating

I am trying to make a set of image views animate in and out from a point, like how an extending menu works, The page is build with the buttons already showing and during the viewDidLayoutSubviews(), I animate them away. 我正在尝试使一组图像视图从一个点开始进出动画,例如扩展菜单的工作方式。该页面是用已经显示的按钮构建的,在viewDidLayoutSubviews()期间,我将它们动画掉了。 When a button is pressed I then animate them out to their original position, all of the animations are based on changing the center of the image view. 当按下按钮时,我会将它们设置为原始位置的动画,所有动画均基于更改图像视图的中心。 The problem I have is for some reason, the animate out is offset to the right by a bit. 我遇到的问题是由于某种原因,动画输出向右偏移了一点。 on large devices this isn't too bad but on smaller devices this is a large problem. 在大型设备上,这还不错,但在小型设备上,这是一个大问题。 all of the UI is built using the autoLayout: 所有UI均使用autoLayout构建:

自动布局内的布局

Here is the code to get set the center locations, this is run before any animation takes place: 这是用于设置中心位置的代码,该代码在发生任何动画之前运行:

        micContainerLocation = micContainer.center
        cameraContainerLocation = cameraContainer.center
        pencilContainerLocation = pencilContainer.center
        calendarContainerLocation = calendarContainer.center

Here is the animation code for animate the buttons out: 这是用于动画化按钮的动画代码:

    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))

            })    

Here is the result: 结果如下:

动画结果

Any advice would be greatly appreciated. 任何建议将不胜感激。 Thanks. 谢谢。

EDIT: 编辑:

Not sure if this helps but here is a picture of the constriants in the auto layout. 不确定这是否有帮助,但这是自动布局中有害对象的图片。

形象鲜明

and a list of the constraints in detail: 以及详细的约束列表:

细节细节

I suspect the problem (or at least part of the problem) is mixing explicit .center values with auto-layout constraints. 我怀疑问题(或问题的至少一部分)是将显式.center值与自动布局约束混合在一起。 It's also possible you are not getting the "true" center values. 也有可能您没有获得“真实的”中心值。

Another approach, using auto-layout only, is to create an array of constraints for the "hidden" positions and another array for the "visible" positions. 仅使用自动布局的另一种方法是为“隐藏”位置创建约束数组,为“可见”位置创建约束数组。 Then deactivate / activate to show / hide the buttons. 然后停用/激活以显示/隐藏按钮。

And... it's easier done than said :) 而且...比说起来容易:)

  • First, layout your buttons and containers in Storyboard as you have already done. 首先,像已经完成的那样在Storyboard中布置按钮和容器。
  • Next, select each of the constraints affecting the leading and trailing edges of the containers. 接下来,选择影响容器前缘和后缘的每个约束。
  • Set those constraints to be Placeholders, so they will be removed at build time (we'll set up the proper constraints in code so we don't need a whole bunch of @IBOutlet s). 将这些约束设置为Placeholders,以便在构建时将其删除(我们将在代码中设置适当的约束,因此我们不需要一堆@IBOutlet )。
  • Then, as you might guess, set up the constraints in your code. 然后,您可能会猜到,在代码中设置约束。

An additional advantage is that the buttons will automatically size / position themselves even if the superview's width changes - such as on device rotation - without the need for any code to re-evaluate the .center properties. 另一个优点是,即使超级视图的宽度发生了变化(例如在设备旋转时),按钮也将自动调整大小/位置,而无需任何代码来重新评估.center属性。

Here is an image of the Storyboard constraint Placeholder setting: 这是演示图板约束占位符设置的图像:

在此处输入图片说明

The basic idea will be: 基本思想是:

Create a set of constraints so the button containers are out-of-view to the left of the left edge. 创建一组约束,以便按钮容器在左边缘的左侧不可见。 That will be the "hidden" constraints. 那将是“隐藏的”约束。

Create a set of constraints so the button containers are in-view, and each aligned / sized appropriately. 创建一组约束,以便按钮容器在视图中,并且每个按钮容器的对齐/大小适当。 That will be the "visible" constraints. 那将是“可见的”约束。

That all may sound complex, but if you look at the following example, I think you'll see there is really very little going on. 听起来似乎很复杂,但是如果您看下面的示例,我想您会发现实际上没有什么事情。

This example should run as-is... just create a new Storyboard and replace the source, and then use the following class. 此示例应按原样运行...只需创建一个新的Storyboard并替换源代码,然后使用以下类。 It's not quite exactly what you have, but it should be close enough that you can use it as a starting point. 它并不完全是您所拥有的,但是应该足够接近以至于您可以将其用作起点。

Here is the code: 这是代码:

//
//  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()
            })

        }

    }

}

and here is the source of the Storyboard: 这是情节提要的源代码:

<?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>

The result (tapping the gray button will animate the buttons in and out): 结果(点击灰色按钮将使按钮的进出动画):

在此处输入图片说明

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

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