ios - 自定义分段控件或..?

标签 ios swift controls

推特截图

there is screenshot from twitter

我想要在 Swift 4 中使用这种类型的分段控件。我研究了 Apple 文档,但找不到我需要的一些东西,例如删除边框、删除角半径等。如何自定义分段控件,如 Twitter 的?或者是否有其他选项卡/分割解决方案?谢谢。

最佳答案

下面是如何自定义 UISegmentedControl 以在选中时显示底部边框:

  • 为分段控件创建一个容器 View ,并使用自动布局将其固定到其 super View 。
  • 分段控件作为 subview 添加到容器 View ,并使用自动布局将其固定到容器 View 的边缘。
  • 创建一个底部下划线 View ,将其作为 subview 添加到容器 View 中,然后对其应用自动布局(参见示例实现)。
  • 然后设置一个事件监听器:在分段控件的值更改事件中,更改底部下划线 View 的原点,使其移动到所选分段下方。
  • 我还添加了一些关于如何格式化分段控件标签的字体和文本颜色的代码,请参见下面的示例。

这是它的样子:

enter image description here

以编程方式创建容器和分段控制 View 的示例实现:

swift 4.2:

import UIKit

class ViewController: UIViewController {

    private enum Constants {
        static let segmentedControlHeight: CGFloat = 40
        static let underlineViewColor: UIColor = .blue
        static let underlineViewHeight: CGFloat = 2
    }

    // Container view of the segmented control
    private lazy var segmentedControlContainerView: UIView = {
        let containerView = UIView()
        containerView.backgroundColor = .clear
        containerView.translatesAutoresizingMaskIntoConstraints = false
        return containerView
    }()

    // Customised segmented control
    private lazy var segmentedControl: UISegmentedControl = {
        let segmentedControl = UISegmentedControl()

        // Remove background and divider colors
        segmentedControl.backgroundColor = .clear
        segmentedControl.tintColor = .clear

        // Append segments
        segmentedControl.insertSegment(withTitle: "First", at: 0, animated: true)
        segmentedControl.insertSegment(withTitle: "Second", at: 1, animated: true)
        segmentedControl.insertSegment(withTitle: "Third", at: 2, animated: true)

        // Select first segment by default
        segmentedControl.selectedSegmentIndex = 0

        // Change text color and the font of the NOT selected (normal) segment
        segmentedControl.setTitleTextAttributes([
            NSAttributedStringKey.foregroundColor: UIColor.black,
            NSAttributedStringKey.font: UIFont.systemFont(ofSize: 16, weight: .regular)], for: .normal)

        // Change text color and the font of the selected segment
        segmentedControl.setTitleTextAttributes([
            NSAttributedStringKey.foregroundColor: UIColor.blue,
            NSAttributedStringKey.font: UIFont.systemFont(ofSize: 16, weight: .bold)], for: .selected)

        // Set up event handler to get notified when the selected segment changes
        segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged), for: .valueChanged)

        // Return false because we will set the constraints with Auto Layout
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        return segmentedControl
    }()

    // The underline view below the segmented control
    private lazy var bottomUnderlineView: UIView = {
        let underlineView = UIView()
        underlineView.backgroundColor = Constants.underlineViewColor
        underlineView.translatesAutoresizingMaskIntoConstraints = false
        return underlineView
    }()

    private lazy var leadingDistanceConstraint: NSLayoutConstraint = {
        return bottomUnderlineView.leftAnchor.constraint(equalTo: segmentedControl.leftAnchor)
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add subviews to the view hierarchy
        // (both segmentedControl and bottomUnderlineView are subviews of the segmentedControlContainerView)
        view.addSubview(segmentedControlContainerView)
        segmentedControlContainerView.addSubview(segmentedControl)
        segmentedControlContainerView.addSubview(bottomUnderlineView)

        // Constrain the container view to the view controller
        let safeLayoutGuide = self.view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            segmentedControlContainerView.topAnchor.constraint(equalTo: safeLayoutGuide.topAnchor),
            segmentedControlContainerView.leadingAnchor.constraint(equalTo: safeLayoutGuide.leadingAnchor),
            segmentedControlContainerView.widthAnchor.constraint(equalTo: safeLayoutGuide.widthAnchor),
            segmentedControlContainerView.heightAnchor.constraint(equalToConstant: Constants.segmentedControlHeight)
            ])

        // Constrain the segmented control to the container view
        NSLayoutConstraint.activate([
            segmentedControl.topAnchor.constraint(equalTo: segmentedControlContainerView.topAnchor),
            segmentedControl.leadingAnchor.constraint(equalTo: segmentedControlContainerView.leadingAnchor),
            segmentedControl.centerXAnchor.constraint(equalTo: segmentedControlContainerView.centerXAnchor),
            segmentedControl.centerYAnchor.constraint(equalTo: segmentedControlContainerView.centerYAnchor)
            ])

        // Constrain the underline view relative to the segmented control
        NSLayoutConstraint.activate([
            bottomUnderlineView.bottomAnchor.constraint(equalTo: segmentedControl.bottomAnchor),
            bottomUnderlineView.heightAnchor.constraint(equalToConstant: Constants.underlineViewHeight),
            leadingDistanceConstraint,
            bottomUnderlineView.widthAnchor.constraint(equalTo: segmentedControl.widthAnchor, multiplier: 1 / CGFloat(segmentedControl.numberOfSegments))
            ])
    }

    @objc private func segmentedControlValueChanged(_ sender: UISegmentedControl) {
        changeSegmentedControlLinePosition()
    }

    // Change position of the underline
    private func changeSegmentedControlLinePosition() {
        let segmentIndex = CGFloat(segmentedControl.selectedSegmentIndex)
        let segmentWidth = segmentedControl.frame.width / CGFloat(segmentedControl.numberOfSegments)
        let leadingDistance = segmentWidth * segmentIndex
        UIView.animate(withDuration: 0.3, animations: { [weak self] in
            self?.leadingDistanceConstraint.constant = leadingDistance
            self?.layoutIfNeeded()
        })
    }

}

关于ios - 自定义分段控件或..?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45391386/

相关文章:

ios - telprompt - 我可以获得通话时长吗?

ios - 如何在 objective-c 中的sqlite DB中存储音频

Swift MQTT libmosquitto cleanSession 设置为 false 但无法设置持久订阅

python - 创建图形过程控制面板

ios - 当 View Controller 弹出或插入导航 Controller 堆栈时如何获得通知

IOS - 在 Cocos2d 中使用 CCCallBlock,小行星游戏

swift - 如何检查 TextView 是否为空

ios - iOS 设备旋转时的 View 和场景不正确

javascript - Javascript 中的 HTML 行 Controller

C# Foreach 更改某些对象属性?