Swift iOS-如何实现具有不同字体大小的多行SegmentedControl

时间:2018-06-19 15:10:32

标签: ios swift nsattributedstring uisegmentedcontrol

我有使用以下两行的SegmentedControl:

// AppDelegate  
UILabel.appearanceWhenContainedInInstancesOfClasses([UISegmentedControl.self]).numberOfLines = 0

enter image description here

问题是线条字体的大小完全相同。 我需要更改每行的titleTextAttributes,以使第二行小于第一行。

我知道我可以在两行中使用它:

segmentedControl.setTitleTextAttributes([NSAttributedStringKey.font : UIFont.systemFont(ofSize: 17))

我该怎么做?

// The SegmentedControl
let segmentedControl: UISegmentedControl = {
    let segmentedControl = UISegmentedControl(items: ["Pizza\n123.1K", "Turkey Burgers\n456.2M", "Gingerale\n789.3B"])
    segmentedControl.translatesAutoresizingMaskIntoConstraints = false
    segmentedControl.tintColor = UIColor.orange
    segmentedControl.backgroundColor = .white
    segmentedControl.isHighlighted = true
    segmentedControl.addTarget(self, action: #selector(selectedIndex(_:)), for: .valueChanged)
    return segmentedControl
}()

1 个答案:

答案 0 :(得分:3)

您将要通过将UIControl子类化来创建自定义控件。这是一个简单的示例:

CustomSegmentedControl.swift

import UIKit
import CoreImage

public class CustomSegmentedControl: UIControl {

    public var borderWidth: CGFloat = 1.0
    public var selectedSegementIndex = 0 {
        didSet {
            self.styleButtons()
        }
    }

    public var numberOfSegments: Int {
        return self.segments.count
    }

    private var buttons: [UIButton] = []
    private var stackView = UIStackView(frame: CGRect.zero)
    private var stackBackground = UIView(frame: CGRect.zero)
    private var segments: [NSAttributedString] = [] {
        didSet {
            for subview in self.stackView.arrangedSubviews {
                subview.removeFromSuperview()
            }
            self.buttons = []
            for i in 0..<segments.count {
                let segment = segments[i]
                self.createAndAddSegmentButton(title: segment)
            }
            self.styleButtons()
        }
    }

    override public init(frame: CGRect) {
        super.init(frame: frame)
        self.setup()
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setup()
    }

    private func setup() {

        self.addSubview(stackBackground)
        self.stackBackground.constrainToBounds(of: self)
        self.addSubview(stackView)
        self.stackView.constrainToBounds(of: self)
        self.stackView.axis = .horizontal
        self.stackView.distribution = .fillEqually
        self.stackView.spacing = borderWidth

        self.layer.cornerRadius = 5.0
        self.layer.borderWidth = borderWidth
        self.clipsToBounds = true
        self.stackBackground.backgroundColor = tintColor
    }

    private func createAndAddSegmentButton(title: NSAttributedString) {
        let button = createSegmentButton(title: title)
        self.buttons.append(button)
        self.stackView.addArrangedSubview(button)
    }

    private func createSegmentButton(title: NSAttributedString) -> UIButton {
        let button = UIButton(frame: CGRect.zero)
        button.titleLabel?.numberOfLines = 0
        button.titleLabel?.textAlignment = .center
        button.setAttributedTitle(title, for: .normal)
        button.addTarget(self, action: #selector(self.actSelected(button:)), for: .touchUpInside)
        return button
    }

    override public var tintColor: UIColor! {
        willSet {
            self.layer.borderColor = newValue.cgColor
            self.stackBackground.backgroundColor = newValue
        }
    }

    public func setSegments(_ segments: [NSAttributedString]) {
        self.segments = segments
    }

    @objc private func actSelected(button: UIButton) {
        guard let index = self.buttons.index(of: button) else {
            print("invalid selection should never happen, would want to handle better than this")
            return
        }
        self.selectedSegementIndex = index
        self.sendActions(for: .valueChanged)
    }

    private func styleButtons() {
        for i in 0..<self.buttons.count {
            let button = self.buttons[i]
            if i == selectedSegementIndex {
                button.backgroundColor = self.tintColor
                button.titleLabel?.textColor = self.backgroundColor ?? .white
            } else {
                button.backgroundColor = self.backgroundColor
                button.titleLabel?.textColor = self.tintColor
            }
        }
    }
}

extension UIView {
    func constrainToBounds(of view: UIView) {
        self.translatesAutoresizingMaskIntoConstraints = false
        let attrs: [NSLayoutAttribute] = [.leading, .top, .trailing, .bottom]
        let constraints = attrs.map { (attr) -> NSLayoutConstraint in
            return NSLayoutConstraint(item: self,
                                      attribute: attr,
                                      relatedBy: .equal,
                                      toItem: view,
                                      attribute: attr,
                                      multiplier: 1.0,
                                      constant: 0)
        }
        NSLayoutConstraint.activate(constraints)
    }
}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var customSegment: CustomSegmentedControl!
    private var segments: [NSAttributedString] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.customSegment.backgroundColor = .white
        self.customSegment.tintColor = .orange

        let pizza = createText(title: "Pizza", subTitle: "123K")
        let turkey = createText(title: "Turkey Burgers", subTitle: "456.2M")
        let gingerAle = createText(title: "Gingerale", subTitle: "789.3B")
        self.segments = [pizza, turkey, gingerAle]
        self.customSegment.setSegments(self.segments)

        self.customSegment.addTarget(self, action: #selector(self.segmentSelectionChanged(control:)), for: .valueChanged)
    }

    @objc private func segmentSelectionChanged(control: CustomSegmentedControl) {
        let segment = self.segments[control.selectedSegementIndex]
        print("selected segment = \(segment.string)")
    }

    func createText(title: String, subTitle: String) -> NSAttributedString {
        let titleStr = NSMutableAttributedString(string: "\(title)\n", attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 16)])
        let subStr = NSAttributedString(string: subTitle, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 10)])
        titleStr.append(subStr)
        return titleStr
    }

}

enter image description here