Как изменить цвет отображения (tintColor) у UIImage в iOS и WatchKit?
1. Изменение tintColor для UIImage в iOS (UIKit)
Вы были на правильном пути. Ключевой момент — изображение должно быть шаблоном (template image). В UIKit цвет tint применяется только к изображениям, у которых режим рендеринга установлен как .alwaysTemplate. Если изображение не является шаблоном, tintColor игнорируется.
Вот полный рабочий пример для iOS:
// 1. Загружаем изображение с режимом шаблона
let originalImage = UIImage(named: "myIcon")
let templateImage = originalImage?.withRenderingMode(.alwaysTemplate)
// 2. Создаём UIImageView
let imageView = UIImageView(image: templateImage)
// 3. Устанавливаем цвет
imageView.tintColor = .systemBlue
// Альтернативный однострочный вариант:
imageView.image = UIImage(named: "myIcon")?.withRenderingMode(.alwaysTemplate)
imageView.tintColor = .red
Важные моменты:
- Изображение должно быть в формате PNG с прозрачными областями (альфа-каналом). Заливка чёрным цветом — стандарт для шаблонов.
- Убедитесь, что в Assets.xcassets для изображения не установлен флаг "Preserve Vector Data" (если это вектор), иначе tint может не сработать.
- Метод
withRenderingMode(.alwaysTemplate)создаёт новый экземпляр UIImage; оригинал не изменяется.
2. Изменение цвета изображения в WatchKit (WatchOS)
К сожалению, в WatchKit нет прямого аналога tintColor для WKInterfaceImage. Однако есть обходное решение — использовать атрибутированные изображения с помощью NSAttributedString и символов SF Symbols.
Вот пример для WatchOS:
// Используем системную иконку (SF Symbol)
let config = UIImage.SymbolConfiguration(pointSize: 24, weight: .regular)
let symbolImage = UIImage(systemName: "star.fill", withConfiguration: config)?
.withRenderingMode(.alwaysTemplate)
// Преобразуем UIImage в данные
if let imageData = symbolImage?.pngData() {
let wkImage = WKImage(imageData: imageData)
// Устанавливаем цвет через tintColor у WKImage (доступно с watchOS 7+)
wkImage.tintColor = .green
myInterfaceImage.setImage(wkImage)
}
Для кастомных изображений (не SF Symbols):
Если вам нужно изменить цвет своей иконки, подготовьте изображение в коде на iOS и передайте его на Watch через WCSession уже с нужным цветом. Либо используйте UIGraphicsImageRenderer для программного изменения цвета:
func tintedImage(original: UIImage, color: UIColor) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: original.size)
return renderer.image { context in
color.setFill()
context.fill(CGRect(origin: .zero, size: original.size))
original.draw(at: .zero, blendMode: .destinationIn, alpha: 1.0)
}
}
// Использование:
let coloredImage = tintedImage(original: myImage, color: .orange)
// Затем передайте coloredImage на Watch
3. Распространённые ошибки
- Изображение не в формате шаблона. Проверьте, что вы вызвали
withRenderingMode(.alwaysTemplate). - Попытка tintColor на UIImage, а не на UIImageView. Свойство tintColor есть только у UIView (и его наследников) и WKImage, но не у самого UIImage.
- Использование JPEG вместо PNG. JPEG не поддерживает альфа-канал, поэтому tint не сработает.
Надеюсь, это поможет! Если остались вопросы — пишите.
<<Альтернативный подход: использование SF Symbols и системных цветов
Если ваше приложение использует только системные иконки (например, из SF Symbols), вы можете упростить код, избавившись от ручной установки withRenderingMode. SF Symbols по умолчанию поддерживают tintColor:
// iOS
let image = UIImage(systemName: "heart.fill")
imageView.image = image
imageView.tintColor = .systemPink // Работает без дополнительных настроек!
// WatchOS (с watchOS 7+)
let config = UIImage.SymbolConfiguration(pointSize: 20)
let symbol = UIImage(systemName: "heart.fill", withConfiguration: config)
let wkImage = WKImage(image: symbol)
wkImage.tintColor = .systemPink
interfaceImage.setImage(wkImage)
Плюсы: не нужно возиться с рендерингом, изображения адаптируются под Dynamic Type и тёмную тему. Минус: ограничены набором символов Apple. Для кастомных иконок используйте первый ответ.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги