在 iOS 13 中处理已更改的 AccessoryType 大小

Posted

技术标签:

【中文标题】在 iOS 13 中处理已更改的 AccessoryType 大小【英文标题】:Handle changed size of AccessoryType in iOS 13 【发布时间】:2020-05-28 12:11:15 【问题描述】:

大约一年前,我向question 询问了如何在UITableView 中特定单元格的最右侧放置AccessoryType.checkmark。这是通过将UIStackView(包含两个标签,见下图)的尾随空间限制为UITableViewCell(=祖父母)而不是ContentView(=父母)硬编码40pts来解决的。

有了这个,复选标记然后在单元格“内”右侧的自己的小空间中居中,但不会影响标签的宽度,甚至不会将ContentView 推到左侧(这将是默认行为)。

昨天将 Xcode 更新到 11.5 并在我的测试设备 (iPhone SE) 上安装 ios 13.5 后,它看起来像这样:

为了使复选标记再次居中,我不得不将尾随空格更改为52pts(简单猜测为recommended,因为50pts太少而55pts太多):

不幸的是,这从Label 2 中占用了相当多的空间,而且看起来也很奇怪,因为复选标记周围有所有不必要的可用空间。

我了解到 Apple 在 iOS 13 中对他们的图标进行了大修,看起来他们也增加了 AccessoryTypes 的大小,这可以解释为什么他们现在需要更多的空间来居中。

问题:如何让复选标记再次使用更少的空间?通过再次减小尺寸或占用侧面的一些空间(是否有选项 3?),但仍使用 AccessoryType

【问题讨论】:

单元格的默认行为是在显示辅助视图时减小内容视图的宽度。当您不希望这样时,选项包括:使用您自己的空白或显示复选标记的附件视图;使用自定义视图而不是附件类型。使用以前的方法确实存在 Apple 会更改布局的风险。 (虽然,附件图像现在在分配的空间中左对齐有点奇怪)。 在我链接的问题中,我遇到了你提到的问题:单元格+它的标签被附件类型推到了左边(有一个图像)。您给了我提示,将UIStackView(包含标签)与祖父母而不是父母一起限制,这使得它看起来像上图所示:标签总是看起来一样,复选标记在“顶部”但没有不影响宽度。第一张图像中的复选标记是“左对齐”,因为灰色部分只有 40pts。这适用于旧复选标记,但显然新复选标记更大,需要 52pts 居中,这太大了。 是的...我理解这个问题。 Apple 确实会在不同版本之间更改 UI 元素。对于您想要的布局,我强烈建议您实现自己的复选标记视图,或所选行的其他一些视觉指示器。 我很不擅长创建图像,而且我自己的复选标记(它必须是复选标记)可能看起来不太好,所以我宁愿使用默认的(另外,它会自动设置那样的颜色)。问题是是否可以保留该符号,但要么将其缩小,要么占用侧面的一些空间。目前,我的应用程序的旧版本在 iOS 12 设备上看起来不错,但在 iOS 13 设备上不好看,我的应用程序的新版本在 iOS 13 上看起来不错,但在 iOS 12 上不好看。我正在寻找一种通用且看起来不错的东西在两个版本上。 【参考方案1】:

Apple 更改 UI 的各个方面并不罕见。例如,“系统”字体在 iOS 版本之间已经更改了几次。在这种情况下,复选标记附件图像的位置似乎已在附件视图空间中左对齐(在 iOS 13 中)。

虽然您经常希望在 Apple 进行更改时更改您的 UI 元素(一个很好的例子是 UISegmentedControl),以便您的应用程序界面与操作系统匹配,但有时您不要。

在这种情况下,为了在 iOS 版本中获得最一致的外观,明智的做法是使用完全自定义的 UI 实现。

这是一个使用 PDF 作为复选标记图像的示例(因此我们可以保留矢量缩放),并将其 Render As 属性设置为 Template Image 使其符合色调着色。

首先,它在 Storyboard 中的外观如下:

我们将使用一个自定义单元类并覆盖它的accessoryType 属性:

class CustomCheckedCell: UITableViewCell 

    @IBOutlet var leftLabel: UILabel!
    @IBOutlet var rightLabel: UILabel!
    @IBOutlet var myAccessoryView: UIImageView!

    override var accessoryType: UITableViewCell.AccessoryType 
        set 
            myAccessoryView.alpha = newValue == .none ? 0.0 : 1.0
        
        get 
            return .none
        
    

    override func awakeFromNib() 
        super.awakeFromNib()
        // we use contrasting colors to design the cell in Storyboard
        //  so set all backgrounds to clear at run-time
        guard let lView = leftLabel.superview, let rView = rightLabel.superview else 
            return
        
        [lView, rView, leftLabel, rightLabel].forEach 
            $0?.backgroundColor = .clear
        
    

我们现在可以使用默认的cell.accessoryType = .checkmarkcell.accessoryType = .none 来显示/隐藏复选标记图像而不影响单元格的布局。

这是一个示例控制器类:

class CustomCheckedCellTableViewController: UITableViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

        // we can set the table view's tint color here (tint's our custom checkMark accessory)
        tableView.tintColor = .red
    

    override func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 30
    

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        if let cell = tableView.cellForRow(at: indexPath) 
            cell.accessoryType = .checkmark
        
    

    override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 
        if let cell = tableView.cellForRow(at: indexPath) 
            cell.accessoryType = .none
        
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

        let cCell = tableView.dequeueReusableCell(withIdentifier: "CustomCheckedCell", for: indexPath) as! CustomCheckedCell

        cCell.leftLabel.text = "Left \(indexPath.row)"
        cCell.rightLabel.text = "Right \(indexPath.row)"

        cCell.accessoryType = (tableView.indexPathForSelectedRow == indexPath) ? .checkmark : .none

        return cCell

    


输出如下所示:

这里是故事板源代码:

<?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="KbA-Q0-LNC">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Custom Checked Cell Table View Controller-->
        <scene sceneID="DAq-F3-sy8">
            <objects>
                <tableViewController id="qt8-QK-wnn" customClass="CustomCheckedCellTableViewController" customModule="iOS9SDK" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="2Gh-42-LWt">
                        <rect key="frame" x="0.0" y="0.0"  />
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <prototypes>
                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="CustomCheckedCell" rowHeight="56" id="r8I-XK-VkK" customClass="CustomCheckedCell" customModule="iOS9SDK" customModuleProvider="target">
                                <rect key="frame" x="0.0" y="28"  />
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="r8I-XK-VkK" id="MvA-eu-x6f">
                                    <rect key="frame" x="0.0" y="0.0"  />
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mQ2-DJ-vUS">
                                            <rect key="frame" x="16" y="0.0"  />
                                            <subviews>
                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bfe-Sh-FxV" userLabel="LView">
                                                    <rect key="frame" x="0.0" y="0.0"  />
                                                    <subviews>
                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hhj-4f-3ME">
                                                            <rect key="frame" x="0.0" y="10"  />
                                                            <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                            <nil key="textColor"/>
                                                            <nil key="highlightedColor"/>
                                                        </label>
                                                    </subviews>
                                                    <color key="backgroundColor" red="0.0" green="0.97680455450000003" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <constraints>
                                                        <constraint firstItem="Hhj-4f-3ME" firstAttribute="top" secondItem="bfe-Sh-FxV" secondAttribute="top" constant="10" id="BXa-Av-XMu"/>
                                                        <constraint firstAttribute="trailing" secondItem="Hhj-4f-3ME" secondAttribute="trailing" id="ND3-SS-NJN"/>
                                                        <constraint firstItem="Hhj-4f-3ME" firstAttribute="leading" secondItem="bfe-Sh-FxV" secondAttribute="leading" id="fhX-ir-pnY"/>
                                                        <constraint firstAttribute="bottom" secondItem="Hhj-4f-3ME" secondAttribute="bottom" constant="10" id="jCn-Ib-SDq"/>
                                                    </constraints>
                                                </view>
                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ydx-kR-Ui2" userLabel="RView">
                                                    <rect key="frame" x="210.5" y="0.0"  />
                                                    <subviews>
                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label 2" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vaR-rB-U1a">
                                                            <rect key="frame" x="0.0" y="10"  />
                                                            <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                            <nil key="textColor"/>
                                                            <nil key="highlightedColor"/>
                                                        </label>
                                                    </subviews>
                                                    <color key="backgroundColor" red="0.0" green="0.97680455450000003" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <constraints>
                                                        <constraint firstItem="vaR-rB-U1a" firstAttribute="top" secondItem="ydx-kR-Ui2" secondAttribute="top" constant="10" id="5LB-SK-csH"/>
                                                        <constraint firstAttribute="bottom" secondItem="vaR-rB-U1a" secondAttribute="bottom" constant="10" id="ghm-bd-7PC"/>
                                                        <constraint firstAttribute="trailing" secondItem="vaR-rB-U1a" secondAttribute="trailing" id="rIn-3p-Lpj"/>
                                                        <constraint firstItem="vaR-rB-U1a" firstAttribute="leading" secondItem="ydx-kR-Ui2" secondAttribute="leading" id="z1q-yz-bd6"/>
                                                    </constraints>
                                                </view>
                                            </subviews>
                                            <constraints>
                                                <constraint firstItem="ydx-kR-Ui2" firstAttribute="width" secondItem="bfe-Sh-FxV" secondAttribute="width" multiplier="0.5" id="4h1-AF-V9L"/>
                                            </constraints>
                                        </stackView>
                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="myCheckmark" translatesAutoresizingMaskIntoConstraints="NO" id="s8x-tM-09v">
                                            <rect key="frame" x="339" y="17"  />
                                            <constraints>
                                                <constraint firstAttribute="width" constant="20" id="4UJ-FQ-7yW"/>
                                                <constraint firstAttribute="width" secondItem="s8x-tM-09v" secondAttribute="height" multiplier="1:1" id="bVw-JC-DCh"/>
                                            </constraints>
                                            <preferredSymbolConfiguration key="preferredSymbolConfiguration" weight="semibold"/>
                                        </imageView>
                                    </subviews>
                                    <constraints>
                                        <constraint firstItem="s8x-tM-09v" firstAttribute="leading" secondItem="mQ2-DJ-vUS" secondAttribute="trailing" constant="12" id="G9K-If-FTj"/>
                                        <constraint firstItem="mQ2-DJ-vUS" firstAttribute="top" secondItem="MvA-eu-x6f" secondAttribute="top" id="HNe-Ks-vip"/>
                                        <constraint firstAttribute="trailingMargin" secondItem="s8x-tM-09v" secondAttribute="trailing" id="M5d-Rz-1R2"/>
                                        <constraint firstItem="mQ2-DJ-vUS" firstAttribute="leading" secondItem="MvA-eu-x6f" secondAttribute="leadingMargin" id="RCj-FT-gww"/>
                                        <constraint firstAttribute="bottom" secondItem="mQ2-DJ-vUS" secondAttribute="bottom" id="azO-kX-4jB"/>
                                        <constraint firstItem="s8x-tM-09v" firstAttribute="centerY" secondItem="mQ2-DJ-vUS" secondAttribute="centerY" constant="-1" id="qpV-6I-bLK"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <connections>
                                    <outlet property="leftLabel" destination="Hhj-4f-3ME" id="WQS-bJ-KeJ"/>
                                    <outlet property="myAccessoryView" destination="s8x-tM-09v" id="hUo-ed-Kyz"/>
                                    <outlet property="rightLabel" destination="vaR-rB-U1a" id="RXC-UG-g5P"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                        <connections>
                            <outlet property="dataSource" destination="qt8-QK-wnn" id="aMA-fV-5cb"/>
                            <outlet property="delegate" destination="qt8-QK-wnn" id="S0n-bN-MLJ"/>
                        </connections>
                    </tableView>
                    <navigationItem key="navigationItem" id="kxZ-av-xIt"/>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="qxa-2p-Cxd" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1556" y="830.73463268365822"/>
        </scene>
        <!--Navigation Controller-->
        <scene sceneID="d0B-12-bYa">
            <objects>
                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="KbA-Q0-LNC" sceneMemberID="viewController">
                    <toolbarItems/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="jcB-K3-ueL">
                        <rect key="frame" x="0.0" y="0.0"  />
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <nil name="viewControllers"/>
                    <connections>
                        <segue destination="qt8-QK-wnn" kind="relationship" relationship="rootViewController" id="rwh-Te-ifH"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="5gD-zl-juz" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="616.79999999999995" y="830.73463268365822"/>
        </scene>
    </scenes>
    <resources>
        <image name="myCheckmark"  />
    </resources>
</document>

以及我们自定义复选标记图像的 PDF 文件(我只是将它放在一个不相关的 GitHub 存储库中,因为我们无法在此处 pst pdf 文件):

https://github.com/DonMag/PDFImagePanZoom/blob/master/myCheckmark.pdf

当您将 pdf 文件添加到资产目录时,不要忘记设置渲染为、保留矢量数据和单一比例:

【讨论】:

以上是关于在 iOS 13 中处理已更改的 AccessoryType 大小的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 Apple 应用商店中已发布 iOS 应用的可用地区

iOS - 在设备设置中,如果我更改时间,即使在应用程序后台、已终止状态下也应该得到通知

无法在 iOS 13 上更改 Main.storyboard 的名称 [Xcode 11 GM 种子 2]

iOS - 处理数据模型更改的正确方法是啥?

处理旋转时更改的 iOS 键盘布局

无论区域设置如何,在批处理文件中拆分 %date%