Là nó có thể để sửa đổi một UIImage
's renderingMode
từ một kịch bản hay xib biên tập viên?
Mục đích là áp dụng tintColor
cho UIImageView
đối tượng cụ thể.
Là nó có thể để sửa đổi một UIImage
's renderingMode
từ một kịch bản hay xib biên tập viên?
Mục đích là áp dụng tintColor
cho UIImageView
đối tượng cụ thể.
Câu trả lời:
Đây là cách bạn có thể thực hiện trong tệp .xib hoặc bảng phân cảnh:
(Obj-C) Tạo một danh mục trên 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) Tạo tiện ích mở rộng cho 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)
}
}
Sau đó, trong Trình kiểm tra danh tính trong tệp xib, hãy thêm thuộc tính thời gian chạy:
Bạn có thể đặt chế độ kết xuất hình ảnh không phải trong .xib
tệp mà trong .xcassets
thư viện.
Sau khi thêm hình ảnh vào thư viện nội dung, hãy chọn hình ảnh và mở trình kiểm tra thuộc tính ở phía bên phải của Xcode. Tìm thuộc tính 'Render As' và đặt nó thành 'template'.
Sau khi thiết lập chế độ vẽ của hình ảnh, bạn có thể thêm một màu sắc đến UIImageView
trong một .xib
hoặc .storyboard
tập tin để điều chỉnh màu sắc hình ảnh.
Điều này đặt thuộc tính trên hình ảnh ở bất kỳ nơi nào nó được sử dụng thay vì chỉ trong một tệp trình tạo giao diện, nhưng trong hầu hết các trường hợp (mà tôi đã gặp) thì đây là hành vi bạn muốn.
Một số điều cần lưu ý:
UIImageView
. Tôi đã không nhìn sâu vào điều đó.UIKitComponents
hình ảnh khác như hình ảnh trong UIButton
's và UIBarButtonItem
'.UIImageView
, vì vậy màu sắc không phải lúc nào cũng hiển thị khi chạy ứng dụng.
Sử dụng chế độ hiển thị mẫu với UIImageView trong bảng phân cảnh hoặc xib rất nhiều lỗi, cả trên iOS 7 và iOS 8.
UIImage không được giải mã đúng cách từ bảng phân cảnh / xib. Nếu bạn kiểm tra thuộc imageView.image.renderingMode
tính trong viewDidLoad
phương thức, bạn sẽ nhận thấy rằng nó luôn như vậy UIImageRenderingModeAutomatic
, ngay cả khi bạn đặt nó thành Hiển thị Dưới dạng Hình ảnh Mẫu trong tệp xcassets của mình.
Để giải quyết vấn đề, bạn phải đặt chế độ kết xuất theo cách thủ công:
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage được giải mã đúng cách và thuộc tính của nó renderingMode
phản ánh những gì đã được chọn trong tệp xcassets nhưng hình ảnh không được tô màu.
Để giải quyết vấn đề, bạn có hai tùy chọn:
tintColor
tính trong Thuộc tính thời gian chạy do người dùng xác định thay vì ngăn kiểm tra thuộc tính.hoặc là
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;
Bạn có thể chọn tùy chọn ưa thích của mình, cả hai đều tô màu đúng cho hình ảnh.
(Nếu bạn đang biên dịch với Xcode 6.2, chỉ cần làm self.imageView.tintColor = self.imageView.tintColor;
là đủ nhưng điều này không hoạt động nữa nếu bạn đang biên dịch với Xcode 6.3)
Nếu bạn cần hỗ trợ cả iOS 7 và iOS 8, bạn sẽ cần cả hai cách giải quyết. Nếu bạn chỉ phải hỗ trợ iOS 8, chỉ cần một giải pháp thay thế.
Cài đặt imageView RenderingMode để sử dụng màu sắc trong bảng phân cảnh có thể được giảm thành một lớp lót:
[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
Sau đó, hình ảnh và màu sắc đều có thể được đặt trong Bảng phân cảnh.
Bạn có thể khắc phục sự cố .xib bằng một tiện ích mở rộng:
import UIKit
// fixing Bug in XCode
// http://openradar.appspot.com/18448072
extension UIImageView {
override open func awakeFromNib() {
super.awakeFromNib()
self.tintColorDidChange()
}
}
Nguồn: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac
Thật ngạc nhiên, con bọ này đã tồn tại khoảng 4-5 năm nay.
Bạn không renderingMode
thể đặt từ storyboard
hoặc xib
. Nó có thể truy cập theo chương trình.
Ví dụ:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Đặt tintColor & Class trong 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
}
}
Nó rất dễ sửa chữa
Chỉ cần tạo UIImageViewPDF lớp và sử dụng nó trong bảng phân cảnh của bạn
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
Một giải pháp khác là tạo một UIImageView
lớp con:
final class TemplateImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
guard let oldImage = image else { return }
image = nil
image = oldImage.withRenderingMode(.alwaysTemplate)
}
}
Sau đó, chỉ cần đặt lớp trong Trình tạo giao diện thành TemplateImageView
.
Cách đơn giản để thiết lập từ 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)
}
}
}
}
Hoạt động tốt trên iOS 10 và Swift 3
Trong iOS 9, thiết lập thuộc tintColor
tính trong Trình tạo giao diện vẫn còn lỗi.
Lưu ý rằng một giải pháp hiệu quả bên cạnh việc viết các dòng sửa đổi trực tiếp ImageView
thuộc tính là đặt Render As: Template Image trong danh mục tài sản và gọi ví dụ:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Tôi đã khắc phục sự cố này bằng cách thêm thuộc tính thời gian chạy tintColor
trong trình tạo giao diện.
LƯU Ý: Bạn vẫn cần đặt hình ảnh của mình được hiển thị dưới dạng hình ảnh mẫu trong tệp Images.xcassets của bạn.
Nếu bạn tạo một IBOutlet, bạn có thể thay đổi nó trong phương thứcakenFromNib của mình như vậy ...
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Mặc dù câu trả lời của @ Moby đúng hơn - câu trả lời này có thể ngắn gọn hơn.
Thật điên rồ, lỗi này vẫn còn trong iOS 12.1! Đối với bảng phân cảnh / xibs: Thêm thẻ vào UIImageView có thể là một giải pháp nhanh chóng.
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)
}
}
}
Trong bảng phân cảnh, chọn UIImageView và chọn trình kiểm tra, đặt thuộc tính renderModeTemplate
= On
Trong bảng phân cảnh