HomeiOS Developmentswift - Updating slider place in a customized TabBar when system orientation...

swift – Updating slider place in a customized TabBar when system orientation modifications in iOS with UIKit


I am attempting to create a customized TabBar with a slider that has the identical width because the buttons inside it. The slider ought to change shade and place primarily based on the index of the button pressed inside the TabBar. My present implementation is proven under, however the issue is that when the system rotates or the app resizes, the slider will get caught within the fallacious place. I’ve tried a number of approaches to unravel this difficulty, however I am beginning to assume that your complete logic behind my implementation may be flawed.

enter image description here

enter image description here

import UIKit

class SlidingTabBar: UIView {
    
    public var tapCallback: ((Int) -> ())?
    non-public let horizontalStack = UIStackView()
    non-public let sliderView = UIView()
    non-public var sliderLeftConstraint: NSLayoutConstraint?
    let objects : [CustomTabBarItem] = CustomTabBarItem.allCases
    
    override init(body: CGRect) {
        tremendous.init(body: body)
        commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        tremendous.init(coder:aDecoder)
        commonInit()
    }
    
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, top: 60)
    }
    
    non-public func commonInit() {
        // Arrange the slider view
        sliderView.backgroundColor = objects[0].shade.withAlphaComponent(0.2)
        sliderView.layer.cornerRadius = 10
        sliderView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(sliderView)
        
        horizontalStack.distribution = .fillEqually
        horizontalStack.alignment = .middle
        horizontalStack.translatesAutoresizingMaskIntoConstraints = false
        addSubview(horizontalStack)

        
        let pad: CGFloat = 8.0
        
        sliderLeftConstraint = sliderView.leftAnchor.constraint(equalTo: horizontalStack.leftAnchor)
        NSLayoutConstraint.activate([
            horizontalStack.topAnchor.constraint(equalTo: topAnchor, constant: pad),
            horizontalStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: pad),
            horizontalStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -pad),
            horizontalStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -pad),
            
            sliderLeftConstraint!,
            sliderView.widthAnchor.constraint(equalTo: horizontalStack.widthAnchor, multiplier: 1.0 / CGFloat(items.count)),
            sliderView.heightAnchor.constraint(equalTo: horizontalStack.heightAnchor),
            sliderView.centerYAnchor.constraint(equalTo: horizontalStack.centerYAnchor)
        ])
                
        for (index, merchandise) in objects.enumerated() {
            let itemView = createTabBarItemView(for: merchandise)
            itemView.tag = index
            horizontalStack.addArrangedSubview(itemView)
            itemView.topAnchor.constraint(equalTo: horizontalStack.topAnchor).isActive = true
            itemView.bottomAnchor.constraint(equalTo: horizontalStack.bottomAnchor).isActive = true
        }
        
        self.layer.cornerRadius = 10.0
        self.backgroundColor = .white
    }
    
    non-public func createTabBarItemView(for merchandise: CustomTabBarItem) -> UIView {
        let itemView = UIView()
        let imageView = UIImageView(picture: merchandise.picture)
        imageView.contentMode = .scaleAspectFit
        imageView.tintColor = merchandise == objects[0] ? merchandise.shade : .grey

        let label = UILabel()
        label.textual content = merchandise.title
        label.textColor = merchandise == objects[0] ? merchandise.shade : .grey
        label.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
        
        let itemStackView = UIStackView(arrangedSubviews: [imageView, label])
        itemStackView.axis = .vertical
        itemStackView.alignment = .middle
        itemStackView.spacing = 2
        itemStackView.translatesAutoresizingMaskIntoConstraints = false
        itemView.addSubview(itemStackView)
        
        NSLayoutConstraint.activate([
            itemStackView.centerXAnchor.constraint(equalTo: itemView.centerXAnchor),
            itemStackView.centerYAnchor.constraint(equalTo: itemView.centerYAnchor),
        ])
        
        itemView.addGestureRecognizer(UITapGestureRecognizer(goal: self, motion: #selector(itemTapped(_:))))
        
        return itemView
    }
    
    @objc non-public func itemTapped(_ recognizer: UITapGestureRecognizer) {
        guard let itemStackView = recognizer.view,
              let indexItem = horizontalStack.arrangedSubviews.firstIndex(of: itemStackView) else { return }
        
        tapCallback?(indexItem)
        UIView.animate(withDuration: 0.3) {
            self.sliderView.backgroundColor = self.objects[indexItem].shade.withAlphaComponent(0.2)
            self.sliderLeftConstraint?.fixed = CGFloat(indexItem) * self.sliderView.bounds.width
            
            self.layoutIfNeeded()
            
            self.horizontalStack.arrangedSubviews.enumerated().forEach { (index, view) in
                if let imageView = (view.subviews.first as? UIStackView)?.arrangedSubviews.first as? UIImageView,
                   let label = (view.subviews.first as? UIStackView)?.arrangedSubviews.final as? UILabel {
                    imageView.tintColor = index == indexItem ? self.objects[index].shade : .grey
                    label.textColor = index == indexItem ? self.objects[index].shade : .grey
                }
            }
        }
    }
}

I additionally created an enum, CustomTabBarItem:

enum CustomTabBarItem: CaseIterable {
    case dwelling, search, messages, profile

    var picture: UIImage? {
        change self {
        case .dwelling: return UIImage(systemName: "home")
        case .search: return UIImage(systemName: "magnifyingglass")
        case .messages: return UIImage(systemName: "message")
        case .profile: return UIImage(systemName: "individual")
        }
    }

    var title: String {
        change self {
        case .dwelling: return "Dwelling"
        case .search: return "Search"
        case .messages: return "Messages"
        case .profile: return "Profile"
        }
    }

    var shade: UIColor {
        change self {
        case .dwelling: return .orange
        case .search: return .blue
        case .messages: return .inexperienced
        case .profile: return .pink
        }
    }
}

Is there a solution to replace the mother or father view when the system rotates or a greater method altogether to attain what I am attempting to perform?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments