I realized a Custom Segment Control with UIView, only the first button works.
When I click on the other buttons, they don't change color, and the first button stays with the active background color.
I would like to give the buttons an on / off effect, but only the first button remains on. I believe the problem is inside the method:
func didSelectButton (at index: Int) {
but I can't find what's missing
import UIKit
@IBDesignable class CustomSegmentedView: UIView {
@IBInspectable var selectedBackgroundColor = Colors.colorViolet1 {
didSet {
self.slideView.backgroundColor = selectedBackgroundColor
}
}
@IBInspectable var selectedTextColor: UIColor = UIColor.white
@IBInspectable var buttonText1: String = ConstantFile.buttonMonitoring {
didSet {
self.buttonTitles[0] = buttonText1
}
}
@IBInspectable var buttonText2: String = ConstantFile.buttonAlert {
didSet {
self.buttonTitles[1] = buttonText2
}
}
@IBInspectable var buttonText3: String = ConstantFile.buttonActivities {
didSet {
self.buttonTitles[2] = buttonText3
}
}
@IBInspectable var buttonText4: String = ConstantFile.buttonSettings {
didSet {
self.buttonTitles[3] = buttonText4
}
}
@IBInspectable var image1: UIImage = UIImage() {
didSet {
self.buttonImages[0] = image1
}
}
@IBInspectable var image2: UIImage = UIImage() {
didSet {
self.buttonImages[1] = image2
}
}
@IBInspectable var image3: UIImage = UIImage() {
didSet {
self.buttonImages[2] = image3
}
}
@IBInspectable var image4: UIImage = UIImage() {
didSet {
self.buttonImages[3] = image4
}
}
@IBInspectable var image1Selected: UIImage = UIImage() {
didSet {
self.buttonSelectImages[0] = image1Selected
}
}
@IBInspectable var image2Selected: UIImage = UIImage() {
didSet {
self.buttonSelectImages[1] = image2Selected
}
}
@IBInspectable var image3Selected: UIImage = UIImage() {
didSet {
self.buttonSelectImages[2] = image3Selected
}
}
@IBInspectable var image4Selected: UIImage = UIImage() {
didSet {
self.buttonSelectImages[3] = image4Selected
}
}
@IBInspectable var startingIndex: Int = 0 {
didSet {
if startingIndex > 3 {
startingIndex = 3
self.didSelectButton(at: startingIndex)
} else if startingIndex < 0 {
startingIndex = 0
self.didSelectButton(at: startingIndex)
} else {
self.didSelectButton(at: startingIndex)
}
}
}
lazy var button1: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("", for: .normal)
button.titleLabel?.font = UIFont.fontHelveticaBold14
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
return button
}()
lazy var button2: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("", for: .normal)
button.titleLabel?.font = UIFont.fontHelveticaBold14
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
return button
}()
lazy var button3: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("", for: .normal)
button.titleLabel?.font = UIFont.fontHelveticaBold14
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
return button
}()
lazy var button4: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("", for: .normal)
button.titleLabel?.font = UIFont.fontHelveticaBold14
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
return button
}()
lazy var stackView: UIStackView = UIStackView(arrangedSubviews: [])
lazy var slideView: UIView = {
var view = UIView(frame: CGRect.zero)
view.backgroundColor = self.selectedBackgroundColor
return view
}()
private var currentIndex: Int = 0
private var buttons: [UIButton] = []
private lazy var buttonTitles:[String] = [buttonText1, buttonText2, buttonText3, buttonText4]
private lazy var buttonImages:[UIImage] = [image1, image2, image3, image4]
private lazy var buttonSelectImages:[UIImage] = [image1Selected, image2Selected, image3Selected, image4Selected]
var delegate: CustomSegmentedViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
self.buttons = [button1, button2, button3, button4]
self.buttonTitles = [buttonText1, buttonText2, buttonText3, buttonText4]
self.buttonImages = [image1, image2, image3, image4]
self.buttonSelectImages = [image1Selected, image2Selected, image3Selected, image4Selected]
button1.sizeToFit()
button2.sizeToFit()
button3.sizeToFit()
button4.sizeToFit()
stackView.addArrangedSubview(button1)
stackView.addArrangedSubview(button2)
stackView.addArrangedSubview(button3)
stackView.addArrangedSubview(button4)
stackView.axis = .horizontal
stackView.distribution = .fillProportionally
stackView.alignment = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(slideView)
self.addSubview(stackView)
stackView.pinEdges(to: self)
button1.addTarget(self, action: #selector(CustomSegmentedView.buttonTapped(sender:)), for: .touchUpInside)
button2.addTarget(self, action: #selector(CustomSegmentedView.buttonTapped(sender:)), for: .touchUpInside)
button3.addTarget(self, action: #selector(CustomSegmentedView.buttonTapped(sender:)), for: .touchUpInside)
button4.addTarget(self, action: #selector(CustomSegmentedView.buttonTapped(sender:)), for: .touchUpInside)
button1.setTitle("", for: .normal)
button2.setTitle("", for: .normal)
button3.setTitle("", for: .normal)
button4.setTitle("", for: .normal)
}
override func layoutSubviews() {
super.layoutSubviews()
button1.setImage(buttonImages[0], for: .normal)
button2.setImage(buttonImages[1], for: .normal)
button3.setImage(buttonImages[2], for: .normal)
button4.setImage(buttonImages[3], for: .normal)
self.setupFirstSelection()
}
@objc func buttonTapped(sender :UIButton!) {
switch sender {
case button1:
didSelectButton(at: 0)
break
case button2:
didSelectButton(at: 1)
break
case button3:
didSelectButton(at: 2)
break
case button4:
didSelectButton(at: 3)
break
default:
break
}
}
func didSelectButton(at index: Int) {
self.delegate?.didSelectPage(index: index)
let oldButton = self.buttons[self.currentIndex]
let newButton = self.buttons[index]
newButton.alpha = 0.0
oldButton.setImage(self.buttonImages[self.currentIndex], for: .normal)
newButton.setImage(self.buttonSelectImages[index], for: .normal)
UIView.animate(withDuration: 0.1) {
oldButton.setTitle("", for: .normal)
newButton.setTitle(self.buttonTitles[index], for: .normal)
self.stackView.layoutSubviews()
self.layoutIfNeeded()
newButton.alpha = 1.0
}
UIView.animate(withDuration: 0.2, delay: 0, options: [], animations: {
self.slideView.frame = newButton.frame
self.layoutIfNeeded()
}, completion: nil)
self.currentIndex = index
}
func setupFirstSelection() {
let index = self.startingIndex
let newButton = self.buttons[index]
newButton.setTitle(self.buttonTitles[index], for: .normal)
newButton.setImage(self.buttonSelectImages[index], for: .normal)
self.stackView.layoutSubviews()
self.slideView.frame = newButton.frame
self.slideView.layer.cornerRadius = self.slideView.frame.height/2.0
self.currentIndex = index
}
}
extension UIView {
func pinEdges(to other: UIView) {
leadingAnchor.constraint(equalTo: other.leadingAnchor).isActive = true
trailingAnchor.constraint(equalTo: other.trailingAnchor).isActive = true
topAnchor.constraint(equalTo: other.topAnchor).isActive = true
bottomAnchor.constraint(equalTo: other.bottomAnchor).isActive = true
}
}
protocol CustomSegmentedViewDelegate {
func didSelectPage(index: Int)
}
CodePudding user response:
issue is in your layoutSubviews() you call every time when you call layoutSubviews() this function automatically set first self.setupFirstSelection()
replace layoutSubviews() by commenting self.setupFirstSelection()
override func layoutSubviews() {
super.layoutSubviews()
button1.setImage(buttonImages[0], for: .normal)
button2.setImage(buttonImages[1], for: .normal)
button3.setImage(buttonImages[2], for: .normal)
button4.setImage(buttonImages[3], for: .normal)
//self.setupFirstSelection()
}