如何使用Storyboard实现红色视图随按钮点击的横向滚动动画
iOS Storyboard实现红色指示器横向滚动动画
需求说明
点击one/two/three三个按钮时,下方红色指示器通过平移动画与被点击按钮的横向中心线对齐,效果如下图:
实现步骤
一、调整Storyboard约束
首先修改原有约束避免冲突,新增可动态修改的对齐约束:
- 找到红色指示器视图(id: qMv-J3-IRX),删除原有
leading to 父容器leadingMargin约束,保留width=60、height=2、top到stackView底部间距为7.5这三个约束 - 给红色指示器添加新约束:centerX与one按钮的centerX相等,约束优先级设为1000
- 将上述新增的centerX约束拖线到关联的ViewController类中,命名为
indicatorCenterX - 将三个按钮依次拖线到ViewController类中作为IBOutlet属性,同时把三个按钮的
Touch Up Inside点击事件都关联到同一个响应方法
二、编写动画逻辑
在ViewController中实现约束更新和动画触发代码:
import UIKit class ViewController: UIViewController { // 红色指示器centerX约束 @IBOutlet weak var indicatorCenterX: NSLayoutConstraint! // 三个按钮属性 @IBOutlet weak var btnOne: UIButton! @IBOutlet weak var btnTwo: UIButton! @IBOutlet weak var btnThree: UIButton! override func viewDidLoad() { super.viewDidLoad() // 初始状态默认对齐第一个按钮 updateIndicatorPosition(target: btnOne, animated: false) } // 三个按钮统一绑定该点击事件 @IBAction func buttonDidClick(_ sender: UIButton) { updateIndicatorPosition(target: sender, animated: true) } private func updateIndicatorPosition(target: UIButton, animated: Bool) { // 计算约束偏移量:目标按钮的横向中心 - 按钮父容器的横向中心 guard let superView = btnOne.superview else { return } indicatorCenterX.constant = target.center.x - superView.center.x if animated { // 触发动画更新布局 UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseInOut) { self.view.layoutIfNeeded() } } else { view.layoutIfNeeded() } } }
原Storyboard完整XML代码
<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="s0d-6b-0kx"> <objects> <viewController id="Y6W-OH-hqX" customClass="ViewController" customModule="testA" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc"> <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d1U-7B-Tgv"> <rect key="frame" x="87" y="384" width="240" height="128"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="eWg-Zb-swh"> <rect key="frame" x="33" y="48.5" width="174" height="31"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zlh-MN-0CO"> <rect key="frame" x="0.0" y="0.0" width="58" height="31"/> <color key="backgroundColor" red="0.59656708079999998" green="0.99476033450000001" blue="0.48015679830000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <state key="normal" title="Button"/> <buttonConfiguration key="configuration" style="plain" title="one"/> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Nhe-kU-2XT"> <rect key="frame" x="58" y="0.0" width="58" height="31"/> <color key="backgroundColor" systemColor="systemTealColor"/> <state key="normal" title="Button"/> <buttonConfiguration key="configuration" style="plain" title="two"/> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xmg-JV-Sut"> <rect key="frame" x="116" y="0.0" width="58" height="31"/> <color key="backgroundColor" red="0.59656708079999998" green="0.99476033450000001" blue="0.48015679830000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <state key="normal" title="Button"/> <buttonConfiguration key="configuration" style="plain" title="three"/> </button> </subviews> </stackView> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qMv-J3-IRX"> <rect key="frame" x="8" y="87" width="60" height="2"/> <color key="backgroundColor" systemColor="systemRedColor"/> <constraints> <constraint firstAttribute="height" constant="2" id="Cbd-ML-DDk"/> <constraint firstAttribute="width" constant="60" id="h9e-vK-yTX"/> </constraints> </view> </subviews> <color key="backgroundColor" systemColor="opaqueSeparatorColor"/> <constraints> <constraint firstItem="eWg-Zb-swh" firstAttribute="centerY" secondItem="d1U-7B-Tgv" secondAttribute="centerY" id="0AA-FD-qJg"/> <constraint firstAttribute="height" constant="128" id="7Wb-jR-WDe"/> <constraint firstItem="eWg-Zb-swh" firstAttribute="centerX" secondItem="d1U-7B-Tgv" secondAttribute="centerX" id="CQD-Td-NtF"/> <constraint firstAttribute="width" constant="240" id="Oc9-es-sz8"/> <constraint firstItem="qMv-J3-IRX" firstAttribute="top" secondItem="eWg-Zb-swh" secondAttribute="bottom" constant="7.5" id="mm1-7c-P1U"/> <constraint firstItem="qMv-J3-IRX" firstAttribute="leading" secondItem="d1U-7B-Tgv" secondAttribute="leadingMargin" id="rob-qn-8zm"/> </constraints> </view> </subviews> <viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> <constraint firstItem="d1U-7B-Tgv" firstAttribute="centerX" secondItem="5EZ-qb-Rvc" secondAttribute="centerX" id="t8W-rw-5oD"/> <constraint firstItem="d1U-7B-Tgv" firstAttribute="centerY" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" id="upa-9K-XOs"/> </constraints> </view> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="137.68115942028987" y="137.94642857142856"/> </scene> </scenes> <resources> <systemColor name="opaqueSeparatorColor"> <color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </systemColor> <systemColor name="systemBackgroundColor"> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </systemColor> <systemColor name="systemRedColor"> <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </systemColor> <systemColor name="systemTealColor"> <color red="0.18823529411764706" green="0.69019607843137254" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </systemColor> </resources> </document>
内容的提问来源于stack exchange,提问作者jiexishede
相关产品推荐
相关产品推荐

