Home > front end >  Swift selectable label
Swift selectable label

Time:04-11

I'm developing an application with a map. Now I build a modal sheet from bottom and I want to implement the map type selection (like google maps).

The problem is that I'm not sure how to build the selectable list of button like this one:

Example

What I'm not understanding is which type of object I need to use? Because I'm trying to build it with buttons but I'm not sure that this is a great solution.

import UIKit

@objc(LayerViewController)
public class LayerViewController: UIViewController {
    
    var selectedIndex: Int = 0
    
    var normal: UIButton = UIButton()
    var satellite: UIButton = UIButton()
    
    var style: [UIButton] = []
        
    override public func viewDidLoad() {
        super.viewDidLoad()
        
        style.append(normal)
        style.append(satellite)
        
        setStyle()
    }
    
    func setStyle() {
        
        normal.frame = CGRect(
            x: 100,
            y: self.view.frame.height * 0.2,
            width: 100,
            height: 100
        )
        normal.setBackgroundImage(UIImage(named: "background"), for: .normal)
        normal.layer.borderColor = .init(red: 0, green: 0, blue: 255, alpha: 1)
        normal.layer.borderWidth = 5
        normal.isSelected = true
        normal.addTarget(self, action: #selector(selectNormal), for: .touchUpInside)
        
        satellite.frame = CGRect(
            x: 300,
            y: self.view.frame.height * 0.2,
            width: 100,
            height: 100
        )
        satellite.setBackgroundImage(UIImage(named: "background"), for: .normal)
        satellite.isSelected = false
        satellite.addTarget(self, action: #selector(selectedSatellite), for: .touchUpInside)
        
        
        self.view.addSubview(normal)
        self.view.addSubview(satellite)
    }
    
    @objc func selectNormal() {
        if (selectedIndex != 0) {
            normal.layer.borderColor = .init(red: 0, green: 0, blue: 255, alpha: 1)
            normal.layer.borderWidth = 5
            normal.isSelected = true
            
            style[selectedIndex].layer.borderColor = .init(red: 0, green: 0, blue: 0, alpha: 0)
            style[selectedIndex].layer.borderWidth = 0
            style[selectedIndex].isSelected = false
            selectedIndex = 0
        }
    }
    
    @objc func selectedSatellite() {
        if (selectedIndex != 1) {
            satellite.layer.borderColor = .init(red: 0, green: 0, blue: 255, alpha: 1)
            satellite.layer.borderWidth = 5
            satellite.isSelected = true
            
            style[selectedIndex].layer.borderColor = .init(red: 0, green: 0, blue: 0, alpha: 0)
            style[selectedIndex].layer.borderWidth = 0
            style[selectedIndex].isSelected = false
            selectedIndex = 1
        }
    }
}

EDIT: This solution seems working but I'm not sure that this is a real solution. Because if I need to add more style I should write a lot of code.

CodePudding user response:

I was thinking to something like :

public class LayerViewController: UIViewController {
    // Type of style to apply
    enum StyleType: Int, CaseIterable {
        case normal = 1
        case satellite = 2
        case terrain = 3
        case explore = 4
        // Add more styles here and increment value
    }
    // Button images
    static let buttonImages: [StyleType:String] =
    [.normal: "normal",
     .satellite: "satellite",
     .terrain: "terrain",
     .explore: "explore"]
        // Add more button images for new styles
    
    // The selected style
    var selectedSyle = StyleType.normal
    
    var buttons: [StyleType:UIButton] = [:]

    override public func viewDidLoad() {
        super.viewDidLoad()
        
        addButton(.normal)
        addButton(.satellite)
        addButton(.terrain)
        addButton(.explore)
        setStyle(selectedSyle)
    }
    
    // Button creation and adding to button dictionary
    func addButton(_ style: StyleType) {
        let x: CGFloat = 100   200 * CGFloat(buttons.count)
        
        let frame = CGRect(
            x: x,
            y: self.view.frame.height * 0.2,
            width: 100,
            height: 100
        )
        if let imageName = Self.buttonImages[style] {
            let button = UIButton(frame: frame)
            
            // Use tag to know which button is touched
            button.tag = style.rawValue
            button.setBackgroundImage(UIImage(named: imageName), for: .normal)
            button.layer.borderColor = .init(red: 0, green: 0, blue: 255, alpha: 1)
            button.layer.borderWidth = 5
            button.isSelected = true
            button.addTarget(self, action: #selector(selectStyle(_:)), for: .touchUpInside)
            buttons[style] = button
            self.view.addSubview(button)
        }
    }

    // Update the style of button when selecting one style
    func setStyle(_ selectedStyle: StyleType) {
        for (style, button) in buttons {
            if style == selectedStyle {
                button.layer.borderColor = .init(red: 0, green: 0, blue: 255, alpha: 1)
                button.layer.borderWidth = 5
                button.isSelected = true
                selectedSyle = style
            } else {
                button.layer.borderColor = .init(red: 0, green: 0, blue: 0, alpha: 0)
                button.layer.borderWidth = 0
                button.isSelected = false
            }
            
        }
    }

    // Called when button touched
    @objc func selectStyle(_ sender: UIButton) {
        // Get style via button tag
        if let selectedStyle = StyleType(rawValue: sender.tag) {
            self.setStyle(selectedStyle)
        }
    }
}
  • Related