Czy można zmodyfikować UIImage
a renderingMode
z edytora scenorysu lub XIB?
Celem jest zastosowanie tintColor
się do konkretnego UIImageView
obiektu.
Czy można zmodyfikować UIImage
a renderingMode
z edytora scenorysu lub XIB?
Celem jest zastosowanie tintColor
się do konkretnego UIImageView
obiektu.
Odpowiedzi:
Oto, jak możesz to zrobić w plikach .xib lub scenorysach:
(Obj-C) Utwórz kategorię na 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) Utwórz rozszerzenie dla 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)
}
}
Następnie w Inspektorze tożsamości w pliku xib dodaj atrybut środowiska uruchomieniowego:
Możesz ustawić tryb renderowania obrazu nie w .xib
pliku, ale w .xcassets
bibliotece.
Po dodaniu obrazu do biblioteki zasobów, wybierz obraz i otwórz inspektor atrybutów po prawej stronie Xcode. Znajdź atrybut „Renderuj jako” i ustaw go na „szablon”.
Po ustawieniu trybu renderowania obrazu, możesz dodać kolor tinty do pliku UIImageView
a .xib
lub .storyboard
, aby dostosować kolor obrazu.
To ustawia właściwość na obrazie, gdziekolwiek jest używany, a nie tylko w jednym pliku konstruktora interfejsu, ale w prawie wszystkich przypadkach (z którymi się spotkałem) jest to zachowanie, które chcesz.
Kilka uwag:
UIImageView
. Nie zagłębiałem się w to głęboko.UIKitComponents
obrazów, takich jak obrazy z plików UIButton
„i UIBarButtonItem
”.UIImageView
, więc kolor odcienia nie zawsze jest wyświetlany podczas uruchamiania aplikacji.
Używanie trybu renderowania szablonu z UIImageView w scenorysie lub xib jest bardzo błędne, zarówno w systemie iOS 7, jak i iOS 8.
UIImage nie jest poprawnie dekodowany z storyboardu / xib. Jeśli sprawdzisz imageView.image.renderingMode
właściwość w viewDidLoad
metodzie, zauważysz, że tak jest zawsze UIImageRenderingModeAutomatic
, nawet jeśli ustawisz ją na Renderuj jako obraz szablonu w pliku xcassets.
Aby obejść ten problem, musisz ręcznie ustawić tryb renderowania:
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage jest prawidłowo zdekodowany, a jego renderingMode
właściwość odzwierciedla to, co zostało wybrane w pliku xcassets, ale obraz nie jest zabarwiony.
Aby obejść ten problem, masz dwie możliwości:
tintColor
właściwość w atrybutach środowiska wykonawczego zdefiniowanych przez użytkownika zamiast w panelu inspektora atrybutów.lub
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;
Możesz wybrać preferowaną opcję, obie odpowiednio zabarwiają obraz.
(Jeśli kompilujesz z Xcode 6.2, wystarczy zrobić self.imageView.tintColor = self.imageView.tintColor;
to, ale to już nie działa, jeśli kompilujesz z Xcode 6.3)
Jeśli chcesz obsługiwać zarówno iOS 7, jak i iOS 8, będziesz potrzebować obu obejść. Jeśli musisz obsługiwać tylko iOS 8, potrzebne jest tylko jedno obejście.
Ustawienie imageView RenderingMode tak, aby używał koloru tinta w serii ujęć, można zredukować do jednowierszowego:
[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
Następnie obraz i kolor tinta można ustawić w Storyboard.
Możesz naprawić problemy z .xib za pomocą rozszerzenia:
import UIKit
// fixing Bug in XCode
// http://openradar.appspot.com/18448072
extension UIImageView {
override open func awakeFromNib() {
super.awakeFromNib()
self.tintColorDidChange()
}
}
Źródło: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac
Niesamowite, ten błąd istnieje już od 4-5 lat.
Nie możesz ustawić renderingMode
ani z, storyboard
ani xib
. Może uzyskać dostęp programowo.
dawny:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Ustaw tintColor & Class w 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
}
}
Bardzo łatwo to naprawić
Po prostu utwórz klasę UIImageViewPDF i użyj jej w swoim storyboardzie
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
Innym rozwiązaniem jest utworzenie UIImageView
podklasy:
final class TemplateImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
guard let oldImage = image else { return }
image = nil
image = oldImage.withRenderingMode(.alwaysTemplate)
}
}
Następnie po prostu ustaw klasę w Interface Builder na TemplateImageView
.
Prosty sposób na ustawienie z 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)
}
}
}
}
Działa dobrze na iOS 10 i Swift 3
W systemie iOS 9 ustawienie tintColor
właściwości w Interface Builder jest nadal błędne.
Zauważ, że działającym rozwiązaniem oprócz pisania linii bezpośrednio modyfikujących ImageView
właściwości jest ustawienie Renderuj jako: Obraz szablonu w katalogu zasobów i wywołanie np .:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Jeśli tworzysz IBOutlet, możesz go zmienić w swojej metodzie awakeFromNib w ten sposób ...
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Chociaż odpowiedź @ Moby'ego jest bardziej poprawna - może być bardziej zwięzła.
Szalony ten błąd nadal występuje w iOS 12.1! W przypadku scenorysów / xibs: dodanie tagu do UIImageView może być szybką naprawą.
Swift 4.2
view.viewWithTag(1)?.tintColorDidChange()
extension UIImageView {
@IBInspectable var renderModeTemplate : Bool {
get{
return image?.renderingMode == .alwaysTemplate
}
set{
image = image?.withRenderingMode(newValue ? .alwaysTemplate:.alwaysOriginal)
}
}
}
W scenorysie wybierz UIImageView i wybierz inspektora, ustaw właściwość renderModeTemplate
= On
In Storyboard
Jak Rudolf również wspomniał powyżej , zdefiniowałbym prostą klasę, taką jak ta:
import UIKit
@IBDesignable class TintImage: UIImageView{
override func layoutSubviews() {
super.layoutSubviews()
image = image?.withRenderingMode(.alwaysTemplate)
}
}
Po tej definicji wystarczy dodać Widok obrazu do scenorysu i wybrać jego klasę niestandardową jako TintImage
. Spowoduje to aktywację wyboru „Odcień” w serii ujęć.