如何在Swift中创建自定义细分控件

时间:2018-10-18 09:27:23

标签: ios iphone swift uisegmentedcontrol

我想创建一个段控件,其功能类似于屏幕截图。 所选段应根据段标题文本加下划线。我已经搜索过了,但是没有找到任何第三方解决方案。 那么如何开发这种段控制呢?

在这里您可以看到底部的线仅延伸到所选线段。

enter image description here

2 个答案:

答案 0 :(得分:1)

GitHub中有一个名为PageMenu的开源项目。请看一下,您甚至可以自定义源文件CAPSPageMenu

https://github.com/PageMenu/PageMenu

enter image description here

要更新选择发际线的宽度,请启用以下属性。

menuItemWidthBasedOnTitleTextWidth

代码:

let parameters: [CAPSPageMenuOption] = [ 
... 
.menuItemWidthBasedOnTitleTextWidth(true),
....]

// Initialize scroll menu
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height), pageMenuOptions: parameters)

请尝试在项目中进行PageMenuDemoStoryboard演示,并更新parameters,如上面的代码所示。

enter image description here

enter image description here

答案 1 :(得分:0)

    import UIKit

extension UIView {
    func constraintsEqualToSuperView() {
        if let superview = self.superview {
            NSLayoutConstraint.activate(
                [
                    self.topAnchor.constraint(
                        equalTo: superview.topAnchor
                    ),
                    self.bottomAnchor.constraint(
                        equalTo: superview.bottomAnchor
                    ),
                    self.leadingAnchor.constraint(
                        equalTo: superview.leadingAnchor
                    ),
                    self.trailingAnchor.constraint(
                        equalTo: superview.trailingAnchor
                    )
                ]
            )
        }
    }
}

protocol ButtonsViewDelegate: class {
    func didButtonTap(buttonView: ButtonsView, index: Int)
}

class ButtonsView: UIView {

    fileprivate let stackView         = UIStackView()
    fileprivate var array             = [String]()
    fileprivate var buttonArray       = [UIButton]()
    fileprivate let baseTag = 300
    weak var delegate: ButtonsViewDelegate?

    override init(frame: CGRect) {
        super.init(frame: frame)

    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    fileprivate func setupUI () {
        setupStackView()
        setupButton()
    }


    convenience init(buttons: [String]) {
        self.init()
        array = buttons
        setupUI()
        //selectButton(atIndex: 0)
    }


    fileprivate func setupStackView() {
        addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.distribution = .fillEqually
        stackView.constraintsEqualToSuperView()
    }

    fileprivate func setupButton() {
        for (i,string) in array.enumerated() {
            let button = UIButton()
            button.setTitle(string.uppercased(), for: .normal)
//            button.backgroundColor = UIColor.lightBackgroundColor().lightened(by: 0.2)
            button.translatesAutoresizingMaskIntoConstraints = false
            button.addTarget(
                self,
                action: #selector(buttonClicked(sender:)),
                for: .touchUpInside
            )
            button.setTitleColor(
                .black,
                for: .normal
            )
            button.titleLabel?.font = UIFont.systemFont(
                ofSize: 14,
                weight: UIFont.Weight.bold
            )

//            let view = UIView.init(frame: CGRect.init(x: 0, y: button.frame.size.height - 1, width: button.frame.size.width, height: 1))

            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = UIColor.clear
            view.tag = baseTag + i
            button.addSubview(view)
            NSLayoutConstraint.activate([
                view.leadingAnchor.constraint(
                    equalTo: button.leadingAnchor
                ),
                view.trailingAnchor.constraint(
                    equalTo: button.trailingAnchor
                ),
                view.bottomAnchor.constraint(
                    equalTo: button.bottomAnchor
                ),
                view.heightAnchor.constraint(
                    equalToConstant: 1
                )
            ])

            stackView.addArrangedSubview(button)
            buttonArray.append(button)
        }
    }

    func selectButton(atIndex index: Int) {
        if index <= buttonArray.count {
            buttonClicked(sender: buttonArray[index])
        }
    }

    @objc private func buttonClicked(sender: UIButton) {
        for button in buttonArray {
            if button == sender {
                button.setTitleColor(
                    UIColor.darkGray,
                    for: .normal
                )
               setUpBottomLine(button: button)
            }else{
                button.setTitleColor(
                    .black,
                    for: .normal
                )
               hideBottomLine(button: button)
            }
        }

        if let index = buttonArray.index(of: sender) {
            delegate?.didButtonTap(buttonView: self, index: index)
        }
    }

    private func setUpBottomLine(button: UIButton) {
        if let index = buttonArray.index(of: button) {
            if let view = button.viewWithTag(baseTag + index) {
                view.backgroundColor = UIColor.red
            }
        }
    }

    private func hideBottomLine(button: UIButton) {
        if let index = buttonArray.index(of: button) {
            if let view = button.viewWithTag(baseTag + index) {
                view.backgroundColor = .clear
            }
        }
    }
}

//how to use
let durationBtns = ButtonsView(buttons: [
    NSLocalizedString(
        "day",
        comment: ""
    ),
    NSLocalizedString(
        "week",
        comment: ""
    ),
    NSLocalizedString(
        "month",
        comment: ""
    ),
    NSLocalizedString(
        "year",
        comment: ""
    )
    ])
durationButtons = durationBtns
durationButtons.selectButton(atIndex: 0)
durationBtns.delegate = self

//handle buttton tap
extension viewController: ButtonsViewDelegate {
    func didButtonTap(buttonView: ButtonsView, index: Int) {
        print(index.description)
    }
}