Цвет фона UIControlSegment больше не прозрачен на iOS13

У меня есть UISegmentedControl. он работал нормально до iOS13 (я установил как backgroundColor, так и tintColor, чтобы очистить). Но сейчас я не получаю того же результата. My SegmentedControl имеет светло-серый слой. Я провел небольшое исследование, но ничего не помогло. (У меня такая же проблема: https://forums.developer.apple.com/thread/123955)

Предыдущее состояние:

текущее состояние - iOS13:

4 ответа

Решение

Спасибо @Maulik Pandya за ответ, я немного улучшил ваш ответ.

extension UISegmentedControl {
  func clearBG() {
    let clearImage = UIImage().imageWithColor(color: .clear)
    setBackgroundImage(clearImage, for: .normal, barMetrics: .default)
    setBackgroundImage(clearImage, for: .selected, barMetrics: .default)
    setDividerImage(clearImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
  }
}

public extension UIImage {
  public func imageWithColor(color: UIColor) -> UIImage {
    let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
    UIGraphicsBeginImageContext(rect.size)
    guard let context = UIGraphicsGetCurrentContext() else { return UIImage()}
    context.setFillColor(color.cgColor)
    context.fill(rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image!
  }
}

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

segmentControl.clearBG()

Вот расширение

extension UISegmentedControl {
    func clearBG() {
        setBackgroundImage(imageWithColor(color: UIColor.white), for: .normal, barMetrics: .default)
        setBackgroundImage(imageWithColor(color: UIColor.white), for: .normal, barMetrics: .default)
        setDividerImage(imageWithColor(color: .white), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    }

    // create a 1x1 image with this color
    private func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context!.setFillColor(color.cgColor);
        context!.fill(rect);
        let image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image!
    }
}

Я также столкнулся с этой проблемой, чтобы соответствовать требованиям дизайна. В моем случае цвет фона SegmentedControl должен быть белым или прозрачным, потому что цвет фона представления также был белым.

Поэтому я просто добавляю белый UImage в фон SegmentControl, и этот трюк у меня сработал.

if (@available(iOS 13.0, *)) {
   [segmentController setBackgroundImage:[UIImage imageNamed:@"someWhiteImage"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}

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

Требуемый дизайн и до iOS 13

После iOS 13

Так что добавление белого фонового изображения сработало для меня

.selectedSegmentTintColor определяет выбранный цвет кнопки и .layer.backgroundColor цвет всего фона UISegmentedControl.

Оказывается, это не сработает для фона, чистого или белого, поскольку в iOS 13 на фон и разделители сегментированного элемента управления добавляется своего рода фоновое изображение.

Обходной путь - создать изображение из цвета с помощью UIGraphicsGetImageFromCurrentImageContext. Попробуй это:

class ViewController: UIViewController {

    @IBOutlet weak var segmentedControl: UISegmentedControl!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        segmentedControl.setiOS12Layout(tintColor: .red)
    }
}

extension UISegmentedControl {

    func setiOS12Layout(tintColor: UIColor) {

        if #available(iOS 13, *) {

            let background = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
             let divider = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))
             self.setBackgroundImage(background, for: .normal, barMetrics: .default)
             self.setBackgroundImage(divider, for: .selected, barMetrics: .default)
             self.setDividerImage(divider, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
             self.layer.borderWidth = 1
             self.layer.borderColor = tintColor.cgColor
             self.setTitleTextAttributes([.foregroundColor: tintColor], for: .normal)
             self.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)

        } else {

            self.tintColor = tintColor
        }
    }
}
extension UIImage {

    convenience init(color: UIColor, size: CGSize) {

        UIGraphicsBeginImageContextWithOptions(size, false, 1)
        color.set()
        let context = UIGraphicsGetCurrentContext()!
        context.fill(CGRect(origin: .zero, size: size))
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        self.init(data: image.pngData()!)!
    }
}

Результат:

Другие вопросы по тегам