Search code examples
iosswiftuikituisegmentedcontrol

I need help changing the background image of a segmented control somehow only red works


I'm new to UIKit and I'm developing a shopping cart page for a project and almost everything went great with little trouble but once I got to working with the segmented control to style it I couldn't do almost anything because it doesn't accept the changes I make. This is the code for the segmented control:

import UIKit

class ShoppingCartViewController: UIViewController {
    
    let segmentedControl = UISegmentedControl()
    let cartView = UIView()
    let wishlistView = UIView()
    
    var customTableViewController: CustomTableViewController?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
 
        
        // Create the table view controller
        customTableViewController = CustomTableViewController()
        customTableViewController?.view.translatesAutoresizingMaskIntoConstraints = false
        cartView.addSubview(customTableViewController!.view)
        
        // Set up segmented control
        segmentedControl.insertSegment(withTitle: "Cart", at: 0, animated: true)
        segmentedControl.insertSegment(withTitle: "Wishlist", at: 1, animated: true)
        segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged(_:)), for: .valueChanged)
        segmentedControl.backgroundColor = UIColor.red
        // Set up cart view
        cartView.clipsToBounds = true
        
        // Set up table view
        customTableViewController?.view.translatesAutoresizingMaskIntoConstraints = false
        cartView.addSubview(customTableViewController!.view)
        
        // Set up wishlist view
        wishlistView.isHidden = true
        
        // Add subviews
        view.addSubview(segmentedControl)
        view.addSubview(cartView)
        view.addSubview(wishlistView)
        
        // Set up constraints
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        cartView.translatesAutoresizingMaskIntoConstraints = false
        wishlistView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 49),
            segmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            segmentedControl.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            segmentedControl.heightAnchor.constraint(equalToConstant: 40),
            
            cartView.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 16),
            cartView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            cartView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            cartView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            customTableViewController!.view.topAnchor.constraint(equalTo: cartView.topAnchor,constant: 28),
            customTableViewController!.view.bottomAnchor.constraint(equalTo: cartView.bottomAnchor, constant: -100),
            customTableViewController!.view.leadingAnchor.constraint(equalTo: cartView.leadingAnchor, constant: 20),
            customTableViewController!.view.trailingAnchor.constraint(equalTo: cartView.trailingAnchor),
        ])
        
        // Add back button to navigation bar
        let backButton = UIBarButtonItem(image: UIImage(systemName: "chevron.left"), style: .plain, target: self, action: #selector(backButtonTapped))
        
        navigationItem.leftBarButtonItem = backButton
    }

        
    @objc func backButtonTapped() {
        // Pop the current view controller off the navigation stack
        navigationController?.popViewController(animated: true)

        // Get a reference to the tab bar controller
        if let tabBarController = navigationController?.tabBarController {
            // Set the home view controller as the selected view controller
            tabBarController.selectedIndex = 0
        }
    }

        
    @objc func segmentedControlValueChanged(_ sender: UISegmentedControl) {
        switch sender.selectedSegmentIndex{
        case 0:
            cartView.isHidden = false
            wishlistView.isHidden = true
        case 1:
            cartView.isHidden = true
            wishlistView.isHidden = false
        default:
            break
        }
    }
}

Extraordinary is that when I try to change the backgroundColor to other backgrounds like white and stuff it doesn't work but when I change it to red it works perfectly. Can someone tell me what I'm doing wrong?


Solution

  • When you check how UISegmentedControl as shown in the images bellow you will find that there are UIImageViews above the background which will give a blur effectImage1

    image2

    And to overcome that situation you have to options First you do as follow

        segmentedControl.backgroundColor = .red // of course you can replace this with white and it will work 
        segmentedControl.selectedSegmentTintColor = .green // this color for the selected segment 
        
        segmentedControl.subviews[0].alpha = 0
        segmentedControl.subviews[1].alpha = 0
    

    but this is not recommended at all

    Second solution is to replace UIImageViews' images using this function setBackgroundImage(_:for:barMetrics:) first you add images in your asset catalog with the color you prefer for example i added white for unselected segment and a green for selected segment

        segmentedControl.setBackgroundImage(UIImage(named: "white"), for: .normal, barMetrics: .default)
        segmentedControl.setBackgroundImage(UIImage(named: "green"), for: .selected, barMetrics: .default)
        segmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.black], for: .normal)
    

    image4