Пишем собственный CustomStepper в Swift

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Тут можно найти реализацию готового проекта

На сегодняшний день во многих приложениях мы можем наблюдать stepper, большинство из них кастомные. Несмотря на то, что Apple предоставляет уже реализацию готового степпера, иногда он не подходит по разным причинам. Это пример подхода к реализации кастомного степпера для кофейни.

Есть разные способы в достижение цели, но сегодня я вам покажу тот, которые не не нашел. В этой статье мы будем использовать верстку кодом, stackView с 2 кнопками (-,+) и лейбл.

Для того, чтобы многократно использовать наш степпер, сделаем его классом, который наследуется от UIView. По сути это полноценный UI-компонент, который можно будет потом взять в свои проекты.

Самое важное - логика, которая будет обрабатывать текущее значения нашего степпера. Для этого будет использовать переменную, которая будет отвечать за текущее значения степпера и обновлять текст лейбла.

final class CustomStepper: UIView {
     private lazy var currentValue = 1
}

Дальше нам нужно создать 2 кнопки и лейбл, из которых и будет состоять наш степпер. Для того, чтобы отслеживать состояние степпера, мы будем использовать enum, который будет управлять состояниями кнопок. Мы использовали теги, для чтобы не делать 2 метода для обработки нажатия кнопок.

    private enum ButtonState: Int, CaseIterable {
        case decrease = 0
        case increase
    }

    private lazy var decreaseButton: UIButton = {
        let button = UIButton()
        button.tag = ButtonState.decrease.rawValue
        button.setTitleColor(.black, for: .normal)
        button.setTitle("-", for: .normal)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        return button
    }()
        
    private lazy var currentStepValueLabel: UILabel = {
        let label = UILabel()
        label.textColor = .black
        label.text = "\(currentValue)"
        label.font = .systemFont(ofSize: 15)
        return label
    }()
        
    private lazy var increaseButton: UIButton = {
        let button = UIButton()
        button.tag = ButtonState.increase.rawValue
        button.setTitle("+", for: .normal)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        button.setTitleColor(.black, for: .normal)
        return button
    }()

Имея все необходимые элементы, мы можем реализовать метод, который отвечает за логику нашего степпера и привязать его к нашим кнопкам.

    //MARK: - Actions
    @objc private func buttonAction(_ sender: UIButton) {
        let buttonState = ButtonState(rawValue: sender.tag)
        
        switch buttonState {
        case .decrease:
            currentValue = currentValue > 1 ? currentValue - 1 : currentValue
        case .increase:
            currentValue += 1
        default:
            return
        }
        currentStepValueLabel.text = "\(currentValue)"
    }

Будем использовать паттерн делегирования, чтобы передать данные степпера в наш контроллер для дальнейшей логики проекта и обновления значения.

protocol CustomStepperOutput: AnyObject {
    func customStepper(_ didChangeValue: Int)
}

protocol CustomStepperInput: AnyObject {
    func update(_ value:Int)
}

Это внутренний интерфейс, через который мы можем проинициализировать счетчик (при необходимости)

//MARK: - CustomStepperInput
extension CustomStepper: CustomStepperInput {
    func update(_ value: Int) {
        currentValue = value
    }
}

Внутри контроллера проинициализируем наш степпер. Контроллер подпишем под делегатом степпера, поэтому контроллер будет реализовывать метод делегата, где получать данные от степпера. С этими данными контроллер может дальше осуществлять логику.

import UIKit

final class MainVC: UIViewController {

    private lazy var stepperView = CustomStepper()
    
    //MARK: - Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        setupConstraints()
    }
    
    //MARK: - Private
    private func setupViews() {
        view.backgroundColor = .white
        view.addSubview(stepperView)
        stepperView.delegate = self
    }
    
    private func setupConstraints() {
        stepperView.snp.makeConstraints { make in
            make.centerX.centerY.equalToSuperview()
        }
    }
}

//MARK: - CustomStepperOutput
extension MainVC: CustomStepperOutput {
    func customStepper(_ didChangeValue: Int) {
        print(didChangeValue)
    }
}

Готово! Вот конечный результат:

Источник: https://habr.com/ru/post/701202/


Интересные статьи

Интересные статьи

На хабре достаточно много пользователей коммуникаторов. Они рассказывали достаточно много историй о том, как их использовали: раскладывали пасьянс, играли в шарики, сидели в интернете, читали книги и ...
К старту курса по ML и DL рассказываем, как воспользоваться API Spotify, чтобы создать систему рекомендаций музыки под настроение на основе алгоритмов ML. Благодаря простоте систему легко настроить по...
Всем хочется получать пассивный доход. Поэтому и пришла идея написать правильного бота, способного зарабатывать на бирже. Как это сделать? К вашему вниманию подробный тут...
Субботний вечер омрачен скандалом - сайт не работает, провайдер негодяй, админы - не специалисты, а сервера - решето. Вызов принят, или почему при всей нелюбви к 1С-Битри...
Начнем сначала В этой статье будет сказ о том, как на Clean Architecture написать API с функциями CR(U)D, где в качестве БД взят Mysql, фреймворк – Echo, ORMapper – GORM. Что делаем ...