Ubah UIImage renderingMode dari file storyboard / xib

93

Apakah mungkin untuk memodifikasi UIImage's renderingModedari storyboard atau xib Editor?

Tujuannya adalah untuk diterapkan tintColorpada UIImageViewobjek tertentu .

Artem Stepanenko
sumber

Jawaban:

101

Berikut cara melakukannya dalam file .xib atau storyboard:

(Obj-C) Buat kategori di 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) Buat ekstensi untuk 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)
    }
}

Kemudian di Identity Inspector di file xib, tambahkan atribut runtime:

masukkan deskripsi gambar di sini

Manusia Salju
sumber
44
Yang saya sukai dari jawaban ini, adalah bahwa ini merupakan jawaban atas pertanyaan.
alga
1
Saya lebih suka membuat subclass UIImageView daripada melakukan pengaturan nilai kunci. Sebab, ini lebih mudah untuk mengatur dan kita bisa menghindari pengaturan angka ke nilai pencacahan. Misalnya: `@implementation TemplateRenderingImageView - (id) initWithCoder: (NSCoder *) aDecoder {self = [super initWithCoder: aDecoder]; jika (self) {self.image = [self.image imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]; } mengembalikan diri; } @ end`
john fantasi
1
Jawaban yang bagus! Tangkapan layar sangat membantu.
BigSauce
1
Tidak berfungsi dengan Launch Screen.xib tentu saja karena Anda tidak dapat menggunakan atribut runtime yang ditentukan pengguna dengannya.
Steve Moser
3
hardcoding 2 sebagai nilai buruk buruk buruk .. Penggunaan katalog xcassets adalah jawaban yang tepat.
tGilani
198

Anda dapat menyetel mode rendering gambar tidak dalam .xibfile, tetapi di .xcassetsperpustakaan.

Setelah menambahkan gambar ke pustaka aset, pilih gambar dan buka inspektur atribut di sisi kanan Xcode. Temukan atribut 'Render As' dan setel ke 'template'.

Setelah mengatur mode rendering gambar, Anda dapat menambahkan warna tint ke UIImageViewdalam file .xibatau .storyboarduntuk menyesuaikan warna gambar.

Ini menyetel properti pada gambar di mana pun itu digunakan, bukan hanya dalam satu file pembuat antarmuka, tetapi dalam hampir semua kasus (yang saya temui) ini adalah perilaku yang Anda inginkan.

Tangkapan layar dari Xcode yang menunjukkan inspektur atribut untuk sebuah gambar

Beberapa hal yang perlu diperhatikan:

  • Warna gambar tidak akan tampak berubah dalam pembuat antarmuka (pada Xcode 6.1.1) tetapi akan berfungsi saat aplikasi dijalankan.
  • Saya mengalami beberapa masalah dengan fitur ini dan dalam beberapa situasi saya harus menghapus dan menambahkan kembali UIImageView. Saya belum memeriksanya secara mendalam.
  • Ini juga berfungsi dengan baik pada UIKitComponentsgambar lain seperti gambar dalam UIButtondan UIBarButtonItem's.
  • Jika Anda memiliki banyak gambar putih yang tidak terlihat di pustaka aset Anda, menjadikannya gambar hitam / transparan dan mengubah mode rendering akan membuat hidup Anda 10x lebih baik.
Anthony Mattox
sumber
15
Sepertinya ada bug dengan warna tint aktif UIImageView, jadi warna tint tidak selalu ditampilkan saat menjalankan aplikasi.
Fogh
@Fogh Saya juga memiliki beberapa bug yang tidak konsisten seperti itu. Apakah pengaturan warna rona secara terprogram memperbaiki ini?
Anthony Mattox
2
Saya dapat mengonfirmasi bahwa ada masalah saat mengatur warna tint di IB. Pengaturan itu bekerja secara terprogram. Saya mengajukan bug # 20305518 untuk itu.
Nikolay Derkach
1
@AxelMuhammad Yup. Sebenarnya hanya saluran alfa yang digunakan, jadi bisa warna apa saja asalkan transparansi yang Anda inginkan.
Anthony Mattox
1
Ini berfungsi sekarang dengan Xcode 7.3 (7D175)! Meskipun jawaban yang diterima adalah solusi yang sangat intuitif, saya lebih suka jawaban ini.
nstein
43

Menggunakan mode rendering template dengan UIImageView di storyboard atau xib sangat bermasalah, baik di iOS 7 dan iOS 8.

Di iOS 7

UIImage tidak didekode dengan benar dari storyboard / xib. Jika Anda memeriksa imageView.image.renderingModeproperti dalam viewDidLoadmetode ini, Anda akan melihat bahwa itu selalu UIImageRenderingModeAutomatic, bahkan jika Anda menyetelnya ke Render As Gambar Template di file xcassets Anda.

Untuk mengatasinya, Anda harus mengatur mode rendering secara manual:

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

Di iOS 8

UIImage didekodekan dengan benar dan renderingModepropertinya mencerminkan apa yang dipilih dalam file xcassets tetapi gambar tidak diwarnai.

Untuk mengatasinya, Anda memiliki dua opsi:

  1. Setel tintColorproperti di Atribut Waktu Proses yang Ditentukan Pengguna, bukan di panel inspektur Atribut.

atau

  1. Setel ulang tintColor secara manual:
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;

Anda dapat memilih opsi yang Anda sukai, keduanya mewarnai gambar dengan benar.

(Jika Anda mengkompilasi dengan Xcode 6.2, melakukan saja self.imageView.tintColor = self.imageView.tintColor;sudah cukup tetapi ini tidak berfungsi lagi jika Anda mengkompilasi dengan Xcode 6.3)

Kesimpulan

Jika Anda perlu mendukung iOS 7 dan iOS 8, Anda memerlukan kedua solusi tersebut. Jika Anda hanya harus mendukung iOS 8, hanya satu solusi yang diperlukan.

0xced
sumber
2
Terima kasih. Hanya solusi # 2 yang berhasil untuk saya di Xcode 7 dan iOS 8.
Surfrider
3
Saya mengonfirmasi bahwa solusi untuk iOS 8 juga berlaku untuk iOS 9.
Michael Pirotte
1
Saya pasti melihat hal yang sama di Xcode 7 - solusi atribut pengguna baik-baik saja. Terima kasih!
Geoffrey Wiseman
menyetel ulang tintColor secara manual di awakeFromNib berhasil! (gambar juga disetel ke template di katalog .xcassets, jika tidak, Anda harus membuat gambar template dari aslinya). Terima kasih!!
tapal kuda7
15

Menyetel imageView RenderingMode untuk menggunakan warna tint di storyboard bisa dikurangi menjadi satu baris:

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

Kemudian gambar dan warna rona semuanya dapat diatur di Papan Cerita.

perantara
sumber
13

Anda dapat memperbaiki masalah .xib dengan ekstensi:

import UIKit

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

Sumber: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac

Luar biasa, bug ini sudah ada sekitar 4-5 tahun sekarang.

nikans
sumber
3
Ini harus dipilih sebagai jawaban
farzadshbfn
Masih bug dan ini masih memperbaikinya pada iOS 12.0.
Sam Soffes
Masih bug di iOS 12.1
Cesare
Orang-orang yang tidak nyata, tidak nyata.
Mat
8

Anda tidak dapat menyetel renderingModedari storyboardatau xib. Itu bisa diakses secara terprogram.

ex:

UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
Mani
sumber
3
Saya pikir, Anda telah membuat kesalahan ketik kecil dalam kode Anda. Baris kedua harusUIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Artem Stepanenko
8

Setel tintColor & Class di 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
    }

}
Dmitry Coolerov
sumber
Ini adalah satu-satunya jawaban yang berhasil pada new swift. Terima kasih.
Simon Moshenko
Tidak berhasil untuk saya karena beberapa alasan aneh ... Apakah itu seharusnya memperbarui warna di papan cerita?
Cesare
4

Sangat mudah untuk memperbaikinya

Cukup buat kelas UIImageViewPDF dan gunakan di storyboard Anda

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
Igor Popov
sumber
3

Solusi lain adalah membuat UIImageViewsubclass:

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

Kemudian setel kelas dalam Interface Builder ke TemplateImageView.

Rudolf Adamkovič
sumber
solusi terbaik !!
Irshad Mohamed
2

Cara sederhana untuk mengatur dari 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)
            }

        }
    }
}

Berfungsi dengan baik di iOS 10 dan Swift 3

Rodrigo
sumber
1

Di iOS 9, pengaturan tintColorproperti di Interface Builder masih bermasalah.

Perhatikan bahwa solusi yang berfungsi selain menulis baris yang secara langsung memodifikasi ImageViewproperti adalah dengan menyetel Render As: Gambar Template dalam katalog aset, dan memanggil misalnya:

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

Saya memperbaiki masalah ini dengan menambahkan atribut runtime tintColordi pembuat antarmuka.

CATATAN: Anda masih perlu mengatur gambar Anda untuk ditampilkan sebagai gambar template di file Images.xcassets Anda.

masukkan deskripsi gambar di sini

Sunil Targe
sumber
0

Jika Anda membuat IBOutlet, Anda dapat mengubahnya dalam metode awakeFromNib seperti ...

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

Meskipun jawaban @ Moby lebih tepat - ini mungkin lebih ringkas.

amergin
sumber
1
Pertanyaannya adalah bagaimana melakukan ini di storyboard (atau xib), bukan dalam kode.
Artem Stepanenko
@artem - ya, maaf, saya tidak bermaksud untuk menyimpulkan bahwa saya punya jawaban untuk pertanyaan Anda. Hanya menunjukkan cara sederhana untuk menangani hal ini melalui IBOutlet
mulai
0

Gila bug ini masih di iOS 12.1! Untuk storyboard / xibs: Menambahkan tag ke UIImageView bisa menjadi perbaikan cepat.

Swift 4.2.0

view.viewWithTag(1)?.tintColorDidChange()
Jayden Irwin
sumber
0
extension UIImageView {

   @IBInspectable var renderModeTemplate : Bool {
       get{
           return image?.renderingMode == .alwaysTemplate
       }

       set{
          image = image?.withRenderingMode(newValue ? .alwaysTemplate:.alwaysOriginal)
       }
   }
}

Di storyboard pilih UIImageView dan pilih inspector, set property renderModeTemplate= On Di Storyboard

Ks 2000
sumber
0

Seperti yang juga disebutkan Rudolf di atas , saya akan mendefinisikan kelas sederhana, seperti ini:

import UIKit

@IBDesignable class TintImage: UIImageView{
    override func layoutSubviews() {
        super.layoutSubviews()
 
        image = image?.withRenderingMode(.alwaysTemplate)
    }
}

Setelah definisi ini, cukup tambahkan Image View ke storyboard dan pilih kelas kustomnya sebagai TintImage. Ini akan mengaktifkan pilihan "Tint" di storyboard.

JustADeveloper
sumber