Let me explain what I want to achieve. I want to create a slider and horizontal list of buttons inside UIStackView and UIScrollView so that buttons can scroll and then UISlider and UIScrollview will be placed inside vertical UIStackView. But the problem is I can scroll the UISlider but the buttons horizontally seem stuck or overlapped with the UIScrolView horizontal and it was not working I tried everything but not able to fix it. I wanted to do it programmatically. Any Help is really helpful
class ViewController: UIViewController {
private var stackView: UIStackView!
private var stackViewNew: UIStackView!
let x: CGFloat = 10
let width: CGFloat = UIScreen.main.bounds.width - 20
var y: CGFloat = 10
var i = 0
let step:Float=10
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = true
v.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 200)
return v
}()
private var stackViewFilter: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = true
v.axis = .vertical
v.backgroundColor = .black
v.alpha = 0.8
v.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 330)
v.frame.origin = CGPoint(x:0 , y: UIScreen.main.bounds.height - 330)
v.distribution = .equalSpacing
v.spacing = 10.0
return v
}()
let horizontalStackView : UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = true
v.axis = .horizontal
v.backgroundColor = .systemPink
v.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 200)
v.distribution = .equalSpacing
v.spacing = 10.0
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
createBottomFilter()
}
@objc func createBottomFilter(){
/*---------- Slider Section ----------*/
let mySlider = UISlider(frame:CGRect(x: 40, y: 10, width: 200, height: 60))
mySlider.minimumValue = 0
mySlider.maximumValue = 100
mySlider.isContinuous = true
mySlider.tintColor = UIColor.green
mySlider.addTarget(self, action: #selector(self.sliderValueDidChange(_:)), for: .valueChanged)
mySlider.translatesAutoresizingMaskIntoConstraints = true
UIView.animate(withDuration: 0.8) {
mySlider.setValue(80.0, animated: true)
}
self.view.addSubview(stackViewFilter)
stackViewFilter.addArrangedSubview(mySlider)
stackViewFilter.addArrangedSubview(scrollView)
self.view.addSubview(scrollView)
mySlider.leadingAnchor.constraint(equalTo: stackViewFilter.leadingAnchor, constant: 8).isActive = true
mySlider.trailingAnchor.constraint(equalTo: stackViewFilter.trailingAnchor, constant: 8).isActive = true
mySlider.topAnchor.constraint(equalTo: stackViewFilter.bottomAnchor, constant: 10).isActive = true
constraintBottom = mySlider.bottomAnchor.constraint(equalTo: scrollView.topAnchor, constant: 40)
constraintBottom?.isActive = true
scrollView.leftAnchor.constraint(equalTo: stackViewFilter.leftAnchor, constant: 0.0).isActive = true
scrollView.topAnchor.constraint(equalTo: mySlider.bottomAnchor, constant: 8.0).isActive = true
scrollView.rightAnchor.constraint(equalTo: stackViewFilter.rightAnchor, constant: 80.0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 8.0).isActive = true
// add the stack view to the scroll view
scrollView.addSubview(horizontalStackView)
horizontalStackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0.0).isActive = true
horizontalStackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0.0).isActive = true
horizontalStackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -30.0).isActive = true
let b = generateButton(title: "Btn 1", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b.translatesAutoresizingMaskIntoConstraints = true
let b1 = generateButton(title: "Btn 2", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b1.translatesAutoresizingMaskIntoConstraints = true
let b2 = generateButton(title: "Btn 3", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b2.translatesAutoresizingMaskIntoConstraints = true
let b3 = generateButton(title: "Btn 4", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b3.translatesAutoresizingMaskIntoConstraints = true
let b4 = generateButton(title: "Btn 5", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b4.translatesAutoresizingMaskIntoConstraints = true
let b5 = generateButton(title: "Btn 6", selectedTitle: "Filter \(i)", iconName: "hellen", scaledToSize:CGSize(width: 90.0, height: 90.0))
b5.translatesAutoresizingMaskIntoConstraints = true
horizontalStackView.addArrangedSubview(b)
horizontalStackView.addArrangedSubview(b1)
horizontalStackView.addArrangedSubview(b2)
horizontalStackView.addArrangedSubview(b3)
horizontalStackView.addArrangedSubview(b4)
horizontalStackView.addArrangedSubview(b5)
horizontalStackView.alignment = .center
}
@objc func generateButton(title: String, selectedTitle: String? = nil, iconName: String, scaledToSize newSize: CGSize) -> UIButton {
let iconName: UIImage? = imageWithImage(UIImage(named: iconName), scaledToSize:CGSize(width: newSize.width, height: newSize.height))
iconName?.withTintColor(.white)
let button = UIButton.vertical(padding: 3)
button.frame = CGRect(x: x, y: y, width: width, height: 80)
button.setImage(iconName, for: .normal)
button.layer.zPosition = 1
button.setTitle(title, for: .normal)
button.setTitle(selectedTitle, for: .selected)
self.view.addSubview(button)
i += 1
y += button.frame.height
return button
}
}
class VerticalButton: UIButton {
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let titleRect = super.titleRect(forContentRect: contentRect)
let imageRect = super.imageRect(forContentRect: contentRect)
return CGRect(x: 0,
y: contentRect.height - (contentRect.height - padding - imageRect.size.height - titleRect.size.height) / 2 - titleRect.size.height,
width: contentRect.width,
height: titleRect.height)
}
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
let imageRect = super.imageRect(forContentRect: contentRect)
let titleRect = self.titleRect(forContentRect: contentRect)
return CGRect(x: contentRect.width/2.0 - imageRect.width/2.0,
y: (contentRect.height - padding - imageRect.size.height - titleRect.size.height) / 2,
width: imageRect.width,
height: imageRect.height )
}
private let padding: CGFloat
init(padding: CGFloat) {
self.padding = padding
super.init(frame: .zero)
self.titleLabel?.textAlignment = .center
}
required init?(coder aDecoder: NSCoder) { fatalError() }
}
extension UIButton {
static func vertical(padding: CGFloat) -> UIButton {
return VerticalButton(padding: padding)
}}