it-swarm.com.ru

Модифицируйте режим рендеринга UIImage из файла раскадровки/xib

Можно ли изменить UIImage's renderingMode из раскадровки или редактора Xib?

Цель состоит в том, чтобы применить tintColor к конкретному объекту UIImageView.

82
Artem Stepanenko

Вот как вы можете сделать это в файлах .xib или раскадровке:

(Obj-C) Создайте категорию на UIImageView:

@interface UIImageView (Utils)

- (void)setImageRenderingMode:(UIImageRenderingMode)renderMode;

@end

@implementation UIImageView (Utils)

- (void)setImageRenderingMode:(UIImageRenderingMode)renderMode
{
    NSAssert(self.image, @"Image must be set before setting rendering mode");
    self.image = [self.image imageWithRenderingMode:renderMode];
}

@end

(Swift 4) Создайте расширение для UIImageView:

extension UIImageView {
    func setImageRenderingMode(_ renderMode: UIImage.RenderingMode) {
        assert(image != nil, "Image must be set before setting rendering mode")
        // AlwaysOriginal as an example
        image = image?.withRenderingMode(.alwaysOriginal)
    }
}

Затем в Identity Inspector в xib-файле добавьте атрибут времени выполнения:

enter image description here

93
Snowman

Вы можете установить режим рендеринга изображения не в файле .xib, а в библиотеке .xcassets.

После добавления изображения в библиотеку ресурсов выберите изображение и откройте инспектор атрибутов в правой части XCode. Найдите атрибут «Render As» и установите для него «template».

После настройки режима рендеринга изображения вы можете добавить оттенок цвета к UIImageView в файле .xib или .storyboard, чтобы настроить цвет изображения.

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

Screenshot of Xcode showing attributes inspector for an image

Несколько вещей, на которые стоит обратить внимание:

  • Цвет изображения не будет изменяться в конструкторе интерфейса (как в Xcode 6.1.1), но будет работать при запуске приложения.
  • Я столкнулся с некоторыми затруднениями с этой функцией, и в некоторых ситуациях мне пришлось удалить и повторно добавить UIImageView. Я не изучал это глубоко.
  • Это также прекрасно работает с другими UIKitComponents, такими как изображения в UIButton и UIBarButtonItem.
  • Если у вас есть куча белых изображений, которые невидимы в вашей библиотеке ресурсов, то сделайте их черными/прозрачными изображениями и измените режим рендеринга, что сделает вашу жизнь в 10 раз лучше.
174
Anthony Mattox

Использование режима рендеринга шаблонов с UIImageView в раскадровке или XIB очень глючно, как на iOS 7, так и на iOS 8.

На iOS 7

UIImage неправильно декодируется из раскадровки/XIB. Если вы проверите свойство imageView.image.renderingMode в методе viewDidLoad, вы заметите, что оно всегда UIImageRenderingModeAutomatic, даже если вы установите его в Render As Template Image в файле xcassets.

Чтобы обойти это, вы должны вручную установить режим рендеринга:

self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

На iOS 8

UIImage правильно декодируется, и его свойство renderingMode отражает то, что было выбрано в файле xcassets, но изображение не окрашено.

Чтобы обойти это, у вас есть два варианта:

  1. Задайте свойство tintColor в Определяемые пользователем атрибуты времени выполнения вместо панели инспектора Атрибуты.

или же

  1. Сбросьте tintColor вручную:
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;

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

(Если вы компилируете с Xcode 6.2, достаточно просто выполнить self.imageView.tintColor = self.imageView.tintColor;, но это больше не работает, если вы компилируете с Xcode 6.3)

Заключение

Если вам нужно поддерживать iOS 7 и iOS 8, вам понадобятся оба обходных пути. Если вам нужно только поддерживать iOS 8, вам понадобится только один обходной путь.

42
0xced

Настройка imageView RenderingMode для использования оттенка цвета в раскадровке может быть уменьшена до одной строки:

[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];

Тогда цвет изображения и оттенок могут быть установлены в раскадровке.

15
middleseatman

Вы можете исправить проблемы .xib с расширением:

import UIKit

// fixing Bug in XCode
// http://openradar.appspot.com/18448072
extension UIImageView {
    override open func awakeFromNib() {
        super.awakeFromNib()
        self.tintColorDidChange()
    }
}

Источник: https://Gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac

Удивительно, эта ошибка существует уже около 4-5 лет.

10
nikans

Вы не можете установить renderingMode из storyboard или xib. Это может получить доступ программно.

например: 

UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
8
Mani

Установите tintColor & Class в раскадровке.

//
//  TintColoredImageView.Swift
//  TintColoredImageView
//
//  Created by Dmitry Utmanov on 14/07/16.
//  Copyright © 2016 Dmitry Utmanov. All rights reserved.
//

import UIKit

@IBDesignable class TintColoredImageView: UIImageView {

    override var image: UIImage? {
        didSet {
            let _tintColor = self.tintColor
            self.tintColor = nil
            self.tintColor = _tintColor
        }
    }


    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialize()
    }

    override init(image: UIImage?) {
        super.init(image: image)
        initialize()
    }

    override init(image: UIImage?, highlightedImage: UIImage?) {
        super.init(image: image, highlightedImage: highlightedImage)
        initialize()
    }

    func initialize() {
        let _tintColor = self.tintColor
        self.tintColor = nil
        self.tintColor = _tintColor
    }

}
8
Dmitry Coolerov

Это очень легко исправить

Просто создайте класс UIImageViewPDF и используйте его в своей раскадровке

IB_DESIGNABLE
@interface UIImageViewPDF : UIImageView

@end

@implementation UIImageViewPDF

- (void) didMoveToSuperview
{
    [super didMoveToSuperview];
    self.image = [self.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    id color = self.tintColor;
    self.tintColor = color;
}

@end
4
Igor Popov

Другое решение заключается в создании подкласса UIImageView:

final class TemplateImageView: UIImageView {
    override func awakeFromNib() {
        super.awakeFromNib()
        guard let oldImage = image else { return }
        image = nil
        image = oldImage.withRenderingMode(.alwaysTemplate)
    }
}

Затем просто установите класс в Интерфейсном Разработчике в TemplateImageView.

3
Rudolf Adamkovič

Простой способ установки из раскадровки:

@IBDesignable
public class CustomImageView: UIImageView {
    @IBInspectable var alwaysTemplate: Bool = false {
        didSet {
            if alwaysTemplate {
                self.image = self.image?.withRenderingMode(.alwaysTemplate)
            } else {
                self.image = self.image?.withRenderingMode(.alwaysOriginal)
            }

        }
    }
}

Отлично работает на iOS 10 и Swift 3

2
Rodrigo

В iOS 9 настройка свойства tintColor в Интерфейсном Разработчике все еще глючит.

Обратите внимание, что рабочим решением помимо написания строк, непосредственно изменяющих свойства ImageView, является установка Render As: Template Image в каталоге ресурсов и вызов, например,

[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
1
yarp

Сумасшедший этот баг все еще в iOS 12.1! Для раскадровок/XIBS: добавление тега в UIImageView может быть быстрым решением.

Swift 4.2

view.viewWithTag(1)?.tintColorDidChange()
0
Jayden Irwin

Если вы создаете IBOutlet, вы можете изменить его в своем методе awakeFromNib, например так ...

self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Хотя ответ @ Moby более точный, он может быть более кратким.

0
amergin

Я исправил эту проблему, добавив атрибут времени исполнения tintColor в конструктор интерфейса.

ПРИМЕЧАНИЕ. Вам все равно нужно будет настроить изображение, которое будет отображаться как изображение шаблона, в файле Images.xcassets.

 enter image description here

0
Sunil Targe