顶部菜单栏中的下划线单个按钮

Underline Single Button from Top menu bar

  1. 如图所示MyTopBar 我在滚动视图中有 5 个 uibuttons。我将其用作 Navigation/Top bar
  2. 我想在5个按钮中只对选定的按钮实现下划线效果。图片Target
  3. 我看到了一些库,但它们并没有像我预期的那样工作
  4. 我会刷新相同的视图,所以这不是很有用
  5. 有人能告诉我实现这种下划线效果的简单方法吗?

有多种方法可以做到这一点。这是一种方法...

  • 将按钮置于水平堆栈视图中
  • 添加一个 UIView 作为你的 "underline view"

你的 "underline view":

  • 将高度限制设置为 4
  • 设置顶部约束等于堆栈视图的底部
  • 设置 widthAnchor 等于第一个按钮 widthAnchor,常量 8(宽 4 磅)
  • 设置 centerXAnchor 等于第一个按钮 centerXAnchor

将宽度和中心锚点连接到自定义 class 中的 @IBOutlet

点击按钮时:

  • 取消激活宽度和 centerX 约束
  • 将它们设置为点击的按钮
  • 重新激活它们
  • 根据需要动画到位

下面是示例实现的代码:

protocol TopBarButtonTapProtocol {
    func didSelect(_ sender: UIButton)
}

class MyTopBar: UIView {

    var delegate: TopBarButtonTapProtocol?

    @IBOutlet var theStack: UIStackView!
    @IBOutlet var uView: UIView!

    @IBOutlet var uWidth: NSLayoutConstraint!
    @IBOutlet var uCenter: NSLayoutConstraint!

    override func didMoveToWindow() {
        super.didMoveToWindow()

        let btns = theStack.arrangedSubviews

        btns.forEach { v in
            guard let btn = v as? UIButton else {
                fatalError("Stack view must contain buttons only!")
            }
            btn.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)
        }

    }

    @objc func didTap(_ sender: UIButton) -> Void {
        uCenter.isActive = false
        uWidth.isActive = false
        uCenter = uView.centerXAnchor.constraint(equalTo: sender.centerXAnchor)
        uWidth = uView.widthAnchor.constraint(equalTo: sender.widthAnchor, constant: 8)
        uCenter.isActive = true
        uWidth.isActive = true
        UIView.animate(withDuration: 0.3) {
            self.layoutIfNeeded()
        }
        delegate?.didSelect(sender)
    }

}

class TestMyTopBarViewController: UIViewController, TopBarButtonTapProtocol {

    @IBOutlet var myTopBar: MyTopBar!

    override func viewDidLoad() {
        super.viewDidLoad()
        myTopBar.delegate = self
    }

    func didSelect(_ sender: UIButton) {
        print("Top Bar button selected:", sender.currentTitle)
    }

}

这里是故事板示例的来源:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="abg-zX-CIL">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Test My Top Bar View Controller-->
        <scene sceneID="Jte-e1-dR6">
            <objects>
                <viewController id="abg-zX-CIL" customClass="TestMyTopBarViewController" customModule="MiniScratch" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="TsC-q0-s74">
                        <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="kx6-5a-S6X" customClass="MyTopBar" customModule="MiniScratch" customModuleProvider="target">
                                <rect key="frame" x="0.0" y="0.0" width="375" height="46"/>
                                <subviews>
                                    <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BXS-ke-LLN">
                                        <rect key="frame" x="0.0" y="0.0" width="375" height="46"/>
                                        <subviews>
                                            <stackView opaque="NO" contentMode="scaleToFill" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="Gtj-bJ-9xt">
                                                <rect key="frame" x="16" y="8" width="406" height="30"/>
                                                <subviews>
                                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ljU-s4-4DJ">
                                                        <rect key="frame" x="0.0" y="0.0" width="65" height="30"/>
                                                        <state key="normal" title="FOR YOU">
                                                            <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                        </state>
                                                    </button>
                                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="242-wz-PkM">
                                                        <rect key="frame" x="81" y="0.0" width="75" height="30"/>
                                                        <state key="normal" title="TRENDING">
                                                            <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                        </state>
                                                    </button>
                                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="c15-qj-lxv">
                                                        <rect key="frame" x="172" y="0.0" width="34" height="30"/>
                                                        <state key="normal" title="NEW">
                                                            <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                        </state>
                                                    </button>
                                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5DP-bs-qBc">
                                                        <rect key="frame" x="222" y="0.0" width="75" height="30"/>
                                                        <state key="normal" title="FEATURED">
                                                            <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                        </state>
                                                    </button>
                                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZfK-40-1VN">
                                                        <rect key="frame" x="313" y="0.0" width="93" height="30"/>
                                                        <state key="normal" title="BOOKMARKS">
                                                            <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                        </state>
                                                    </button>
                                                </subviews>
                                            </stackView>
                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="974-mZ-VM1">
                                                <rect key="frame" x="12" y="38" width="73" height="4"/>
                                                <color key="backgroundColor" systemColor="systemRedColor" red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <constraints>
                                                    <constraint firstAttribute="height" constant="4" id="rvK-8e-XTq"/>
                                                </constraints>
                                            </view>
                                        </subviews>
                                        <constraints>
                                            <constraint firstItem="Gtj-bJ-9xt" firstAttribute="trailing" secondItem="Zfb-Kx-C2I" secondAttribute="trailing" constant="16" id="4nw-75-kgv"/>
                                            <constraint firstItem="974-mZ-VM1" firstAttribute="centerX" secondItem="ljU-s4-4DJ" secondAttribute="centerX" id="9Ig-gt-a62"/>
                                            <constraint firstItem="Gtj-bJ-9xt" firstAttribute="leading" secondItem="Zfb-Kx-C2I" secondAttribute="leading" constant="16" id="EGu-UL-6tD"/>
                                            <constraint firstItem="Gtj-bJ-9xt" firstAttribute="bottom" secondItem="Zfb-Kx-C2I" secondAttribute="bottom" id="Fby-qZ-GyD"/>
                                            <constraint firstItem="974-mZ-VM1" firstAttribute="width" secondItem="ljU-s4-4DJ" secondAttribute="width" constant="8" id="GNh-W8-umn"/>
                                            <constraint firstItem="974-mZ-VM1" firstAttribute="top" secondItem="Gtj-bJ-9xt" secondAttribute="bottom" id="QeJ-UW-lPh"/>
                                            <constraint firstItem="Gtj-bJ-9xt" firstAttribute="top" secondItem="Zfb-Kx-C2I" secondAttribute="top" constant="8" id="gXv-a7-43N"/>
                                            <constraint firstItem="x1k-em-xS5" firstAttribute="bottom" secondItem="Gtj-bJ-9xt" secondAttribute="bottom" constant="8" id="yQ5-dH-18H"/>
                                        </constraints>
                                        <viewLayoutGuide key="contentLayoutGuide" id="Zfb-Kx-C2I"/>
                                        <viewLayoutGuide key="frameLayoutGuide" id="x1k-em-xS5"/>
                                    </scrollView>
                                </subviews>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstAttribute="trailing" secondItem="BXS-ke-LLN" secondAttribute="trailing" id="1Qh-mv-QIl"/>
                                    <constraint firstItem="BXS-ke-LLN" firstAttribute="top" secondItem="kx6-5a-S6X" secondAttribute="top" id="XBR-Uf-huR"/>
                                    <constraint firstItem="BXS-ke-LLN" firstAttribute="leading" secondItem="kx6-5a-S6X" secondAttribute="leading" id="YyI-HM-ve8"/>
                                    <constraint firstAttribute="bottom" secondItem="BXS-ke-LLN" secondAttribute="bottom" id="ioI-y3-Lmd"/>
                                </constraints>
                                <connections>
                                    <outlet property="theStack" destination="Gtj-bJ-9xt" id="5XU-eX-2NB"/>
                                    <outlet property="uCenter" destination="9Ig-gt-a62" id="TxH-Bf-Hy0"/>
                                    <outlet property="uView" destination="974-mZ-VM1" id="BZ0-ne-Fcb"/>
                                    <outlet property="uWidth" destination="GNh-W8-umn" id="aFq-4f-sQu"/>
                                </connections>
                            </view>
                        </subviews>
                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                        <constraints>
                            <constraint firstItem="kx6-5a-S6X" firstAttribute="top" secondItem="u6w-w1-8iK" secondAttribute="top" id="KhJ-Id-pdJ"/>
                            <constraint firstItem="kx6-5a-S6X" firstAttribute="trailing" secondItem="u6w-w1-8iK" secondAttribute="trailing" id="R2z-YZ-Vkl"/>
                            <constraint firstItem="kx6-5a-S6X" firstAttribute="leading" secondItem="u6w-w1-8iK" secondAttribute="leading" id="ifV-RN-a6g"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="u6w-w1-8iK"/>
                    </view>
                    <navigationItem key="navigationItem" id="cpA-Qb-gmu">
                        <barButtonItem key="rightBarButtonItem" systemItem="add" id="mAr-W2-GXa">
                            <connections>
                                <action selector="addBtnPressed:" destination="abg-zX-CIL" id="OIu-lZ-j2s"/>
                            </connections>
                        </barButtonItem>
                    </navigationItem>
                    <connections>
                        <outlet property="myTopBar" destination="kx6-5a-S6X" id="Ssi-YG-3F2"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="wfE-oG-abp" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1703" y="1657"/>
        </scene>
    </scenes>
</document>

下面是 运行 时的样子,按钮向左滚动,"Featured" 按钮被选中: