Как я могу сохранить цвет изображения UIButton от сброса до значения по умолчанию? - PullRequest
0 голосов
/ 29 мая 2018

Этот вопрос касается Swift 4, Xcode 9.3.1.

Процесс изменения цвета кнопки изображения хорошо документирован.Это не проблема.

Этот вопрос касается ПОЧЕМУ цвет кнопки изображения сбрасывается на цвет по умолчанию, если кнопка оказывается целью внутри IBAction, и что делать соб этом.

Я создал новый проект в XCode, чтобы продемонстрировать то, что я вижу.Это проект, имеющий IBAction в контроллере представления, который пытается изменить цвет изображений на кнопке.Я добавил в приложение три кнопки (oneButton, twoButton, threeButton) и связал их, чтобы у каждой из них были следующие выходы:

outlets defined for the typical button

Для каждой кнопки определено другое изображение.Вот пример:

example of image named 'local'

А вот ViewController:

import UIKit

class ViewController: UIViewController {

  @IBOutlet weak var oneButton: UIButton!
  @IBOutlet weak var twoButton: UIButton!
  @IBOutlet weak var threeButton: UIButton!

  override func viewDidLoad() {
    super.viewDidLoad()
  }
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  @IBAction func myAction(sender: UIButton) {
    let oneImageView = oneButton.imageView
    if sender == oneButton {
      print("oneButton")
      oneImageView?.setImageColor(color: UIColor.red)
    } else if sender == twoButton {
      print("twoButton")
      oneImageView?.setImageColor(color: UIColor.blue)
    } else if sender == threeButton {
      print("threeButton")
      oneImageView?.setImageColor(color: UIColor.purple)
    }
  }
}

extension UIImageView {
  func setImageColor(color: UIColor) {
    let templateImage = self.image?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
    self.image = templateImage
    self.tintColor = color
  }
}

При нажатии на каждый значок отображается соответствующий текст вОкно вывода (oneButton, twoButton, threeButton), в зависимости от того, какое из них было нажато.Это работает нормально.

При запуске приложения цвет первого изображения черный (по умолчанию), как и ожидалось.

При нажатии twoButton цвет на первом изображении изменяется насиний, как и ожидалось.

Нажатие threeButton вызывает изменение цвета на первом изображении на фиолетовый, как и ожидалось.

Нажатие oneButton приводит к сбросу цвета на первом изображении напо умолчанию (черный).Это НЕ ожидается.

Я думаю, что происходит, потому что, поскольку кнопка в настоящее время обрабатывает системное событие (касание), цвет, который я устанавливаю, стирается из-занекоторый системный процесс.

Я изменил код так, чтобы вместо Touch Up Inside, myAction() был вызван Touch Down, и цвет первого изображения стал красным!Но только при прикосновении ... как только я отпустил, цвет вернулся к значению по умолчанию.

Я хотел бы иметь возможность прикоснуться к oneButton и изменить его на любой цвет в кодеи не изменяйте его по умолчанию на цвет.

ADDITION / EDIT

Приведенный выше код снова и снова устанавливает режим рендеринга изображения.Я понимаю, что не должно быть необходимым для этого.Но когда я этого не делал, цвета не менялись, когда приложение запускалось в симуляторе.Код выше, по крайней мере, меняет цвет изображения, если к нему не прикасаться.В приведенном ниже коде, хотя соответствующая часть if / else в myAction() выполняется, настройка .tintColor не оказывает никакого влияния, независимо от того, по какому элементу щелкнули.Я пробовал с experiment true и false, но безрезультатно.

class ViewController: UIViewController {

  @IBOutlet weak var oneButton: UIButton!
  @IBOutlet weak var twoButton: UIButton!
  @IBOutlet weak var threeButton: UIButton!

  var oneImageView: UIImageView!
  var oneImage: UIImage!

  override func viewDidLoad() {
    super.viewDidLoad()
    oneImageView = oneButton.imageView
    oneImage = oneImageView?.image
    let experiment = true
    if experiment {
      oneImageView?.image = UIImage(named: "image")?.withRenderingMode(.alwaysTemplate)
    } else {
      oneImage.withRenderingMode(.alwaysTemplate)
      oneImageView.image = oneImage
    }
  }
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  @IBAction func myAction(sender: UIButton) {
    //let oneImageView = oneButton.imageView
    let tintColor: UIColor = {
      print("switch doesn't work here for some reason")
      if sender == oneButton {
        print("oneButton")
        return .red
      } else if sender == twoButton {
        print("twoButton")
        return .blue
      } else if sender == threeButton {
        print("threeButton")
        return .purple
      } else {
        return .cyan
      }
    }()
    oneImageView?.tintColor = tintColor
  }
}

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Установить шаблонное изображение

Короткий ответ: изображение, к которому вы хотите применить цвет, необходимо обозначить как шаблонное изображение.Если это обозначение сделано в инспекторе атрибутов актива изображения, будет работать весь код исходного вопроса.Любые вызовы .withRenderingMode(.alwaysTemplate) станут ненужными.

В инспекторе атрибутов

Если изображение не установлено как Шаблонное изображение , цвет не будет применен.

Способ, которым в настоящее время работает (Xcode 9.4, Swift 4.1), заключается в установке изображения в шаблонное изображение в Инспекторе атрибутов GUI.

set template image attribute in GUI

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

В коде

Установка изображения для шаблонаизображение в коде выглядит так, как будто оно должно работать, но, по крайней мере с Xcode 9.4, Swift 4.1, на симуляторе оно не имеет постоянства;первое касание пользователя сбрасывает его.

В приведенном ниже коде .withRenderingMode(.alwaysTemplate) заставляет значок становиться шаблоном, но , как только пользователь касается значка в первый раз, он снова становится рендерингом по умолчанию. Этоверно для смоделированного iPhone (не тестировал на физическом устройстве).

override func viewDidLoad() {
  super.viewDidLoad()
  oneImageView = oneButton.imageView
  // NOT PERMANENT
  oneImageView?.image = UIImage(named:   "image")?.withRenderingMode(.alwaysTemplate) 
}
0 голосов
/ 29 мая 2018

Вам не нужно устанавливать изображение снова и снова, просто установите изображение один раз в качестве шаблона и измените цвет оттенка позже.Кроме того, лучше использовать switch вместо нескольких if s.

override func viewDidLoad() {
    super.viewDidLoad()

    oneImageView?.image = UIImage(named: "image").withRenderingMode(.alwaysTemplate)
}

@IBAction func myAction(_ sender: UIButton) {
    let tintColor: UIColor = {
        switch sender {
            case oneButton: return .red
            case twoButton: return .blue
            case threeButton: return .purple
            default: return .clear
        }
    }()

    oneImageView?.tintColor = tintColor
}
...