UISegmentedControl TintColor в цвет градиента

Я пытаюсь установить цвет оттенка UIsegmentedControl для выбранного сегмента в градиентный цвет, и я не могу этого сделать.

Я пытаюсь следить за этой статьей https://www.bethedev.com/2019/02/set-gradient-tint-color-for-segmented.html

Пытаюсь использовать этот код:

segmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.white],for: UIControl.State.normal)
        segmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.white],for: UIControl.State.selected)  

fileprivate func updateGradientBackground() {
        let sortedViews = segmentedControl.subviews.sorted( by: { $0.frame.origin.x < $1.frame.origin.x } )
        for (_, view) in sortedViews.enumerated() {
//            let gradientImage = gradient(size: segmentedControl.frame.size, color: [UIColor.cyan,UIColor.blue])!
            view.backgroundColor = UIColor(patternImage: UIImage(named: "segmentedRectangle.png")!)
            view.tintColor = UIColor.clear
        }
    }

Я ожидаю, что только один сегмент будет иметь цвет изображения segmentedRectangle.png, но он отображается на всем сегментированном элементе управления, например это.


person Kris RaduhaSt    schedule 20.08.2019    source источник


Ответы (1)


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

 let segmentedControl: UISegmentedControl = {
       let view =  UISegmentedControl(items: ["Pounds", "Kilograms"])
        view.selectedSegmentIndex = 0
        view.tintColor = .black
        view.backgroundColor = .white
        view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 40, height: 20)
        /// Gradient
        let gradient = CAGradientLayer()
        gradient.frame =  CGRect(x: 0, y: 0, width:  UIScreen.main.bounds.width - 40, height: 20)
        let leftColor = UIColor.red
        let rightColor = UIColor.purple
        gradient.colors = [leftColor.cgColor, rightColor.cgColor]
        gradient.startPoint = CGPoint(x: 0, y: 0.5)
        gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
        /// Create gradient image
        UIGraphicsBeginImageContext(gradient.frame.size)
        gradient.render(in: UIGraphicsGetCurrentContext()!)
        let segmentedControlImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        // Normal Image
        let rect: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size);
        let context:CGContext = UIGraphicsGetCurrentContext()!;
        context.setFillColor(UIColor.white.cgColor)
        context.fill(rect)
        let normalImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        /// Set segmentedControl image
        view.setBackgroundImage(normalImage, for: .normal, barMetrics: .default)
        view.setBackgroundImage(segmentedControlImage, for: .selected, barMetrics: .default)
        return view
    }()

Использование: в ViewDidLoad установите представление заголовка navigationItem в качестве сегментированного элемента управления следующим образом:


self.navigationItem.titleView = segmentedControl

Вывод

Я думаю, что с несколькими модификациями / настройками вы можете получить то, что хотите, Ура :)

Раскадровка/InterfaceBuilder

Просто вызовите это внутри своего ViewDidLoad и передайте свое имя выхода при вызове функции: -

   func configureSegementedControl(segmentedControl: UISegmentedControl) {
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.tintColor = .black
        segmentedControl.backgroundColor = .white
        segmentedControl.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 40, height: 20)
        /// Gradient
        let gradient = CAGradientLayer()
        gradient.frame =  CGRect(x: 0, y: 0, width:  UIScreen.main.bounds.width - 40, height: 20)
        let leftColor = UIColor.red
        let rightColor = UIColor.purple
        gradient.colors = [leftColor.cgColor, rightColor.cgColor]
        gradient.startPoint = CGPoint(x: 0, y: 0.5)
        gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
        /// Create gradient image
        UIGraphicsBeginImageContext(gradient.frame.size)
        gradient.render(in: UIGraphicsGetCurrentContext()!)
        let segmentedControlImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        // Normal Image
        let rect: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size);
        let context:CGContext = UIGraphicsGetCurrentContext()!;
        context.setFillColor(UIColor.white.cgColor)
        context.fill(rect)
        let normalImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        /// Set segmentedControl image
        segmentedControl.setBackgroundImage(normalImage, for: .normal, barMetrics: .default)
        segmentedControl.setBackgroundImage(segmentedControlImage, for: .selected, barMetrics: .default)
    }
person Mussa Charles    schedule 20.08.2019
comment
спасибо, Мусса, могу я вызвать все в viewDidLoad()? - person Kris RaduhaSt; 20.08.2019
comment
Да, я добавил способ вызвать его в последней части кода. В вашем ViewDidLoad, если ваш VC встроен в navigationController, установите его следующим образом: - self.navigationItem.titleView = segmentedControl - person Mussa Charles; 20.08.2019
comment
@KrisRaduhaSt, ​​если это решило вашу проблему, не забудьте отметить это как принятый ответ :) - person Mussa Charles; 20.08.2019
comment
Мусса Очень ценю вашу помощь, последний вопрос: у меня уже есть существующий слабый @IBOutlet var segmentedControl: UISegmentedControl! как связать это с написанным вами кодом? и изменение цвета сегмента при выборе? - person Kris RaduhaSt; 20.08.2019
comment
pastebin.com/EVgs6vn5 Я почти закончил, но не уверен, куда сопоставить представление в последних двух строках. - person Kris RaduhaSt; 20.08.2019
comment
Ой, потому что я создал свой программно, поэтому мне пришлось сделать let segmentedControl... {}() для вашего случая, поскольку вы используете построитель интерфейсов, вам нужно только взять внутреннее содержимое перед возвратной частью и переименовать это представление с вашим именем выхода внутри viewDidLoad. - person Mussa Charles; 20.08.2019
comment
В конце я добавил дополнительную функцию, которая поможет вам связать вашу розетку, еще раз проверьте мой ответ в конце с этим заголовком: StoryBoard/InterfaceBuilder - person Mussa Charles; 20.08.2019
comment
Проверьте еще раз, я немного изменил. - person Mussa Charles; 20.08.2019
comment
Большое спасибо Мусе. Ты самый лучший. - person Kris RaduhaSt; 20.08.2019
comment
С удовольствием, счастливого кодирования :) - person Mussa Charles; 20.08.2019