简体   繁体   中英

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. 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:

自动布局内的布局

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

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

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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