В зависимости от бизнеса к продуктам обычно предъявляются два требования:
Требование 1: Сделать все черно-белым.
Требование 2: Сделать определенный интерфейс черно-белым.
Грубая реализация:
Вариант первый:
Сервер отправляет все черные (серые) картинки, а цвет шрифта поддерживает динамическую доставку.Это
нормально, если интерфейс один, но если заменить все картинки, нагрузка будет слишком большая
Вариант 2:
Это примерно включает в себя: изображение, цвет UILabel, цвет UIButton, webView, видео и т. д.
Для изображения обычно используется UIImageView для отображения, поэтому используйте обмен методом во время выполнения, чтобы позволить методу setImage: использовать свой собственный.
Затем добавьте фильтр к картинке в приватном методе.
+ (void) load { Method customMethod = class_getInstanceMethod([self class], @selector(setImage:)); Метод originMethod = class_getInstanceMethod([собственный класс], @selector(gl_setImage:)); method_exchangeImplementations(customMethod, originMethod);//方法交换}
- (void)gl_setImage:(UIImage *)image { //Чёрно-белое, 1 означает открытый BOOL isOpenWhiteBlackModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"kIsShowBlackWhiteModel"]; if (isOpenWhiteBlackModel == 1) { [self gl_setImage :[ сам gl_grayImage:изображение]]; } еще { [сам gl_setImage:изображение]; } }
- (UIImage *)gl_grayImage:(UIImage *)image { //UIKBSplitImageView是为了键盘 if (image == nil || [self.superview isKindOfClass:NSClassFromString(@"UIKBSplitImageView")]) { return image; } //滤镜处理 //CIPhotoEffectNoir黑白 //CIPhotoEffectMono单色 NSString *filterName = @"CIPhotoEffectMono"; CIFilter *filter = [CIFilter filterWithName:filterName]; CIImage *inputImage = [[CIImage alloc] initWithImage:image]; [фильтр setValue: inputImage forKey: kCIInputImageKey]; CGImageRef cgImage = [self.filterContext createCGImage:filter.outputImage fromRect:[степень inputImage]]; UIImage *resultImg = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
вернуть результатImg;
}
- (CIContext *)filterContext { CIContext *con = objc_getAssociatedObject(self, @selector(filterContext)); if (!con) { con = [[CIContext alloc] initWithOptions:nil]; self.filterContext = кон; } вернуть кон; }
- (void) setFilterContext:(CIContext *)filterContext { objc_setAssociatedObject(self, @selector(filterContext), filterContext, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
H5 выделен серым цветом — классификация
Файл WKWebView+blackWhiteModel.m:
#import "WKWebView+blackWhiteModel.h"
#import <objc/runtime.h>
@implementation WKWebView (blackWhiteModel)
+ (void) load { Method customMethod = class_getInstanceMethod([self class], @selector(gl_initWithFrame:configuration:)); Метод originMethod = class_getInstanceMethod([собственный класс], @selector(initWithFrame:configuration:)); method_exchangeImplementations(customMethod, originMethod);//方法交换}
- (instancetype) gl_initWithFrame: (CGRect) конфигурация кадра: (WKWebViewConfiguration *) конфигурация
{ BOOL isOpenWhiteBlackModel = [[NSUserDefaults standardUserDefaults] boolForKey: @"kIsShowBlackWhiteModel"]; if (isOpenWhiteBlackModel) { // js — NSString *jScript = @"var filter = '-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%); -ms-filter:grayscale(100% ); -o-filter: оттенки серого (100 %) filter: оттенки серого (100 %); ';document.getElementsByTagName ('html') [0].style.filter = 'оттенки серого (100 %)';"; // 注入 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScriptjectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
// 配置对象
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
конфигурация = wkWebConfig;
WKWebView *webView = [self gl_initWithFrame: конфигурация кадра: конфигурация];
вернуть веб-просмотр;
}
return [self gl_initWithFrame: конфигурация кадра: конфигурация];
}
@конец
Существует проблема с приведенным выше решением, потому что это заменяющий метод инициализации, который приведет к тому, что веб-представление до переключателя будет окрашено в цвет 0, а веб-представление после переключателя станет серым 1. Поэтому обязательно подтвердите, что результат запроса на переключение до создания webView
или позже
H5 неактивен — один
Может быть неактивен для одного H5
То же, что и код js выше:
BOOL isOpenWhiteBlackModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"kIsShowBlackWhiteModel"];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userController = [[
WKUserContentController alloc]
init]; { // Режим «День памяти» заменяет общую тему цвет wkView [userController addUserScript:[self getJsStr]]; }
-(WKUserScript *)getJsStr{ NSString *jScript = @"var filter = '-webkit-filter: оттенки серого (100%); -moz-filter: оттенки серого (100%); -ms-filter: оттенки серого (100%); -o-filter: оттенки серого (100%) filter: оттенки серого (100%); ';document.getElementsByTagName ('html') [0].style.filter = 'оттенки серого (100%)';"; // 注入 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScriptjectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; вернуть wkUScript; }
Для других классификаций UILabel, UIButton и т. д. см.:
https://github.com/GeLeis/App_NoirDemo
третье решение:
Обработка изображения аналогична Решению 2
, но цвета Label, View и т. д. больше не классифицируются один за другим, а классификация Color изменяется напрямую.
+ (void)load { // 关键方法交换 Method customMethod = class_getClassMethod([self class], @selector(gl_colorWithRed:green:blue:alpha:)); Метод originMethod = class_getClassMethod([собственный класс], @selector(colorWithRed:green:blue:alpha:)); method_exchangeImplementations(customMethod, originMethod);//方法交换}
+ (UIColor *)gl_colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { // Если это монохромный режим (черно-белый режим), среднее значение r, g, b value //будь то черное или белое, 1 означает открытый BOOL isOpenWhiteBlackModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"kIsShowBlackWhiteModel"]; if (isOpenWhiteBlackModel) { //r, g, b корректировка веса для предотвращения появления, 1 0 0, 0 1 0 ,0 0 1 тот же результат //0,2126, 0,7152, 0,0722 Эти три рассчитаны в соответствии с силой человеческого глаза для трехцветного восприятия поверхности r, g, b CGFloat яркость = (красный * 0,2126 + 0,7152 * зеленый + 0,0722 * синий); return [self gl_colorWithRed:яркость зеленого:яркость синего:яркость альфа:альфа]; } return [self gl_colorWithRed:красный зеленый:зеленый синий:синий альфа:альфа]; }
iOS реализует черно-белый режим приложения
Вариант четвертый:
Больше не через метод времени выполнения, а напрямую добавить серый фильтр в представление
//Получить значение цвета RGBA
CGFloat r,g,b,a;
[[UIColor lightGrayColor] getRed:&r green:&g blue:&b alpha:&a]; //
Создать идентификатор фильтра
cls = NSClassFromString(@"CAFilter");
id filter = [cls filterWithName:@"colorMonochrome"];
//Установка параметров фильтра
[filter setValue:@[@(r),@(g),@(b),@(a)] forKey:@"inputColor "] ;
[filter setValue:@(0) forKey:@"inputBias"];
[filter setValue:@(1) forKey:@"inputAmount"];
//Установить для окна
self.window.layer.filters = [NSArray arrayWithObject: фильтр];
Значения r, g, b и a можно изменить напрямую вместо [UIColor lightGrayColor]
Если это просто определенный контроллер A, A.view.layer.filters = [NSArray arrayWithObject:filter];
просто установите его
Страница приложения iOS неактивна
Конечно, можно использовать и другие фильтры.
id cls = NSClassFromString(@"CAFilter");
id filter = [cls filterWithName:@"colorSaturate"];
[фильтр setValue:@(0) forKey:@"inputAmount"];
//Создание окна
self.window.layer.filters = [NSArray arrayWithObject:filter];
CAFilter — это частный метод Apple, который может быть отклонен, поэтому этот метод не используется.
окончательный подход
Добавить представление, которое не получает события кликов
@интерфейс ZRLandlordHPGrayView : UIView
@конец
@реализация ZRLandlordHPGrayView
- (UIView *) hitTest: (CGPoint) точка withEvent: (UIEvent *) событие
{ return nil; }
@конец
Затем в интерфейсе, который должен отображать черно-белый режим, добавьте следующий метод:
- (void)showGrayViewWithSuperView:(UIView *)superView
{ //Этот метод используется для хранения черно-белого режима BOOL isOpenWhiteBlackModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"kIsShowBlackWhiteModel"]; if (isOpenWhiteBlackModel) { if ( @ available( iOS 12.0, *)) {//Поддерживает только ZRLandlordHPGrayView 12 и выше *overlay = [[ZRLandlordHPGrayView alloc] initWithFrame:superView.bounds]; overlay.userInteractionEnabled = NO; overlay.translatesAutoresizingMaskIntoConstraints = false; UIColor grayColor] overlay.layer.compositingFilter = @"saturationBlendMode" [superView addSubview:overlay];
[superView BringSubviewToFront: наложение];
}
}
}
Этот метод поддерживает только 12 и выше.Посмотрев
на наше приложение, в основном очень мало ниже 12, поэтому я, наконец, выбрал этот метод.
Другие справочные статьи:
Обсуждение решения по посерению интерфейса iOS
Режим траурного дня iOS
с использованием черной магии на iOS для достижения глобального решения по посерению изображения одним щелчком мыши
Интерфейс приложения iOS черно-белая обработка (обработка в оттенках серого) (подготовлено ко дню траура)