Цвет градиента оттенка в сегментном контроле - PullRequest
0 голосов
/ 02 июля 2018

Я получаю градиентное изображение этим методом

func gradient(size:CGSize,color:[UIColor]) -> UIImage?{
    //turn color into cgcolor
    let colors = color.map{$0.cgColor}
    //begin graphics context
    UIGraphicsBeginImageContextWithOptions(size, true, 0.0)
    guard let context = UIGraphicsGetCurrentContext() else {
        return nil
    }
    // From now on, the context gets ended if any return happens
    defer {UIGraphicsEndImageContext()}
    //create core graphics context
    let locations:[CGFloat] = [0.0,1.0]
    guard let gredient = CGGradient.init(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as NSArray as CFArray, locations: locations) else {
        return nil
    }
    //draw the gradient
    context.drawLinearGradient(gredient, start: CGPoint(x:0.0,y:size.height), end: CGPoint(x:size.width,y:size.height), options: [])
    // Generate the image (the defer takes care of closing the context)
    return UIGraphicsGetImageFromCurrentImageContext()
}

Затем я устанавливаю tintColor сегментированного элемента управления на градиент:

    let gradientImage = gradient(size: listSegmentedControl.frame.size, color: [UIColor.black, UIColor.red])!
    listSegmentedControl.tintColor = UIColor(patternImage: gradientImage)

и это не работает. Однако тот же код работает для установки backgroundColor:

    let gradientImage = gradient(size: listSegmentedControl.frame.size, color: [UIColor.black, UIColor.red])!
    listSegmentedControl.backgroundColor = UIColor(patternImage: gradientImage)

У кого-нибудь есть идеи, почему? Мне действительно нужно установить градиент tintColor. Любая помощь очень ценится.

EDIT:

В идеале я хочу, чтобы мой сегментированный элемент управления выглядел так:

enter image description here

1 Ответ

0 голосов
/ 02 июля 2018

Это известный хак для изменения цвета оттенка UISegmentedControl

   let sortedViews = listSegmentedControl.subviews.sorted( by: { $0.frame.origin.x < $1.frame.origin.x } )

    for (index, view) in sortedViews.enumerated() {
        if index == listSegmentedControl.selectedSegmentIndex {
            view.tintColor = UIColor(patternImage: gradientImage)
        } else {
            view.tintColor = UIColor.gray //Whatever the color of non selected segment controller tab
        }
    }

Хотя выглядит как уродливый хак, я уже давно пользуюсь им и, кажется, довольно прямолинеен. Надеюсь, это поможет.

EDIT:

Это то, что тебе нужно, приятель?

enter image description here

Если да, дай мне знать, я отправлю код для того же.

РЕДАКТИРОВАТЬ 2:

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

Отказ от ответственности:

Как упомянуто rmaddy в его комментариях ниже, это хак и использует недокументированный (хотя и полный публичный API), но очень хорошо известный хак для изменения цвета оттенка UISegemntedControl, который существует как Насколько iOS 5 (вот насколько я помню, позвольте мне знать, если я не прав)

Поэтому используйте ответ с осторожностью, учитывая, что в будущих выпусках iOS Apple может изменить структуру подпредставлений в UISegemntedControl и может повлиять на вашу O / P. Ничто из того, что я вижу, не приведет к сбою, но может повлиять на способ отображения O / P на экране.

Я объявил переменную, так что GradientImage может быть сгенерирован только один раз, но ваша реализация должна использовать ее так, как вы хотите

var gradientImage : UIImage! = nil

В ViewDidLoad Я инициализирую gradientImage и UISegmentedControl как

override func viewDidLoad() {
        super.viewDidLoad()
        gradientImage = gradient(size: segmentControl.frame.size, color: [UIColor.black, UIColor.red])!

        //I have specified custom font need not necessarily be used
        //Font color attribute is important though, usually `UISegementedControl` title takes color from tint color, because we might need a different color for text to highlight above gradient color am using custom font colors

        let font = UIFont(name: "HelveticaNeue-Medium", size: 20)
        segmentControl.setTitleTextAttributes([NSFontAttributeName : font!, NSForegroundColorAttributeName : UIColor.blue], for: .normal)
        segmentControl.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.white], for: .selected)

        //Set the border color and border to `UISegmentedControl` and also make it round corner

        segmentControl.layer.borderColor = UIColor(patternImage: gradientImage).cgColor
        segmentControl.layer.borderWidth = 2
        segmentControl.layer.masksToBounds = true
        segmentControl.layer.cornerRadius = 10

        //In order to update the selected Segment tint and background color we need to call multiple statements every time selection changes hence I have moved it to the function and called it in viewDidLoad

        updateGradientBackground()
    }

Наконец, определение функции updateGradientBackground совпадает с тем, которое я опубликовал в своем исходном ответе

fileprivate func updateGradientBackground() {
        let sortedViews = segmentControl.subviews.sorted( by: { $0.frame.origin.x < $1.frame.origin.x } )
        for (index, view) in sortedViews.enumerated() {
            if index == segmentControl.selectedSegmentIndex {
                //very important thing to notice here is because tint color was not honoring the `UIColor(patternImage` I rather used `backgroundColor` to create the effect and set clear color as clear color
                view.backgroundColor = UIColor(patternImage: self.gradientImage)
                view.tintColor = UIColor.clear
            } else {
                //very important thing to notice here is because tint color was not honoring the `UIColor(patternImage` I rather used `backgroundColor` to create the effect and set clear color as clear color
                view.backgroundColor = UIColor.white //Whatever the color of non selected segment controller tab
                view.tintColor = UIColor.clear
            }
        }
    }

Наконец, в IBAction UISegmentedControl, просто позвоните

@IBAction func segmentControllerTapped(_ sender: UISegmentedControl) {
    self.updateGradientBackground()
}

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...