web-dev-qa-db-fra.com

Modifier UIImage renderingMode à partir d'un fichier storyboard/xib

Est-il possible de modifier un UIImage d'un renderingMode à partir d'un éditeur de storyboard ou xib?

L'objectif est d'appliquer tintColor à l'objet UIImageView particulier.

82
Artem Stepanenko

Voici comment vous pouvez le faire dans des fichiers .xib ou storyboard:

(Obj-C) Créez une catégorie sur 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) Créez une extension pour 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)
    }
}

Ensuite, dans l'inspecteur d'identité du fichier xib, ajoutez un attribut d'exécution:

enter image description here

93
Snowman

Vous pouvez définir le mode de rendu des images non pas dans le fichier .xib, mais dans une bibliothèque .xcassets.

Après avoir ajouté une image à une bibliothèque d'actifs, sélectionnez-la et ouvrez l'inspecteur d'attributs situé à droite de Xcode. Recherchez l'attribut "Render As" et définissez-le sur "template".

Après avoir défini le mode de rendu d'une image, vous pouvez ajouter une couleur de nuance à la variable UIImageView dans un fichier .xib ou .storyboard pour ajuster la couleur de l'image.

Cela définit la propriété sur l'image partout où elle est utilisée plutôt que dans un seul fichier de constructeur d'interface, mais dans presque tous les cas (que j'ai rencontrés), il s'agit du comportement souhaité.

Screenshot of Xcode showing attributes inspector for an image

Quelques points à noter:

  • La couleur de l'image ne semble pas avoir changé dans le générateur d'interface (à partir de Xcode 6.1.1), mais fonctionnera lors de l'exécution de l'application.
  • J'ai eu quelques problèmes avec cette fonctionnalité et dans certaines situations, j'ai dû supprimer et rajouter la variable UIImageView. Je n'ai pas approfondi cette question.
  • Cela fonctionne également très bien avec les autres variables UIKitComponents, telles que les images de UIButton 's et UIBarButtonItem' s.
  • Si vous avez un tas d'images blanches qui sont invisibles dans votre bibliothèque d'actifs, les transformer en images noires/transparentes et changer le mode de rendu rendra votre vie 10 fois plus agréable.
174
Anthony Mattox

L'utilisation du mode de rendu des modèles avec UIImageView dans un storyboard ou xib est très problématique, à la fois sous iOS 7 et iOS 8.

Sur iOS 7

UIImage n'est pas correctement décodé à partir du storyboard/xib. Si vous inspectez la propriété imageView.image.renderingMode dans la méthode viewDidLoad, vous remarquerez qu'elle est toujours UIImageRenderingModeAutomatic, même si vous la définissez sur Render As Template Image dans votre fichier xcassets.

Pour contourner ce problème, vous devez définir manuellement le mode de rendu:

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

Sur iOS 8

UIImage est correctement décodé et sa propriété renderingMode reflète ce qui a été choisi dans le fichier xcassets mais l'image n'est pas colorée.

Pour contourner le problème, vous avez deux options:

  1. Définissez la propriété tintColor dans le volet Attributs d'exécution définis par l'utilisateur au lieu du volet Inspecteur Attributs.

ou

  1. Réinitialiser manuellement la teinteCouleur:
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;

Vous pouvez choisir votre option préférée, les deux teinter correctement l'image.

(Si vous compilez avec Xcode 6.2, il suffit de faire self.imageView.tintColor = self.imageView.tintColor; mais cela ne fonctionne plus si vous compilez avec Xcode 6.3)

Conclusion

Si vous devez prendre en charge à la fois iOS 7 et iOS 8, vous aurez besoin des deux solutions de contournement. Si vous devez uniquement prendre en charge iOS 8, une seule solution de contournement est nécessaire.

42
0xced

Définir imageView RenderingMode pour utiliser la couleur de teinte dans le scénarimage peut être réduit à une ligne:

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

Ensuite, l’image et la couleur de la teinte peuvent être définies dans le Storyboard.

15
middleseatman

Vous pouvez corriger les problèmes de .xib avec une extension:

import UIKit

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

Source: https://Gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac

Incroyable, ce bogue existe depuis environ 4-5 ans maintenant.

10
nikans

Vous ne pouvez pas définir renderingMode à partir de storyboard ou xib. Il pourrait accéder par programme.

ex: 

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

Définissez teinteCouleur & Classe dans Storyboard.

//
//  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

C'est très facile à réparer

Créez simplement la classe UIImageViewPDF et utilisez-la dans votre storyboard

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

Une autre solution consiste à créer une sous-classe UIImageView:

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

Ensuite, définissez simplement la classe dans Interface Builder sur TemplateImageView.

3
Rudolf Adamkovič

Un moyen simple d'être défini à partir de Storyboard:

@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)
            }

        }
    }
}

Fonctionne bien sur iOS 10 et Swift 3

2
Rodrigo

Dans iOS 9, la définition de la propriété tintColor dans Interface Builder est toujours problématique.

Notez qu'une solution de travail en plus d'écrire des lignes modifiant directement les propriétés ImageView consiste à définir Render As: Template Image dans le catalogue d'actifs et à appeler, par exemple:

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

Fou ce bug est toujours dans iOS 12.1! Pour les storyboards/xibs: Ajouter une balise à UIImageView peut être une solution rapide.

Swift 4.2

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

Si vous créez un IBOutlet, vous pouvez le changer dans votre méthode awakeFromNib comme suit ...

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

Alors que la réponse de @ Moby est plus correcte, cela pourrait être plus succinct.

0
amergin

J'ai résolu ce problème en ajoutant l'attribut d'exécution tintColor dans le générateur d'interface.

REMARQUE: vous devrez toujours définir le rendu de votre image en tant que modèle dans votre fichier Images.xcassets.

 enter image description here

0
Sunil Targe