ビジネスにもよりますが、通常、製品には次の 2 つの要件があります。
要件 1: すべてを白黒に設定する
要件 2: 特定のインターフェイスを白黒に設定する
大まかな実装:
オプション 1:
サーバーはすべて黒(グレー)の画像を送信し、フォントの色は動的配信に対応しています
.これはインターフェイスが1つしかない場合は問題ありませんが、すべての画像を置き換えると負荷がかかりすぎます.
オプション II:
大まかに言うと、画像、UILabel の色、UIButton の色、webView、ビデオなどです。
画像の場合、通常は UIImageView を使用して表示するため、実行時にメソッド交換を使用して setImage: メソッドを独自のものにします。
次に、プライベート メソッドで画像にフィルターを追加します
+ (void)load { Method customMethod = class_getInstanceMethod([self クラス], @selector(setImage:)); メソッド originMethod = class_getInstanceMethod([self クラス], @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 :[ self gl_grayImage:image]]; } else { [self gl_setImage:image]; } }
- (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]; [filter setValue:inputImage forKey:kCIInputImageKey]; CGImageRef cgImage = [self.filterContext createCGImage:filter.outputImage fromRect:[入力画像範囲]]; UIImage *resultImg = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
resultImg を返します。
}
- (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 クラス], @selector(gl_initWithFrame:configuration:)); メソッド originMethod = class_getInstanceMethod([self クラス], @selector(initWithFrame:configuration:)); method_exchangeImplementations(customMethod, originMethod);// メソッド交换}
- (instancetype)gl_initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
{ 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:grayscale(100%) filter:grayscale(100%);';document.getElementsByTagName('html')[0].style.filter = 'grayscale(100%)';"; // 注入 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript InjectionTime: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:フレーム構成:構成];
webView を返します。
戻り
ます [self gl_initWithFrame:フレーム構成:構成];
} @
終了
iOS APPインターフェース 白黒処理(グレースケール処理)(記念日用に用意)
上記の解決策では、init メソッドの置き換えであり、スイッチが 0 の前の webView が色付きになり、スイッチが 1 の後の webView が灰色になるという問題があります。切り替えるかどうかをリクエストした結果は、 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:grayscale(100%);-moz-filter:grayscale(100%); -ms-filter:grayscale(100%); -o-filter:grayscale(100%) filter:grayscale(100%);';document.getElementsByTagName('html')[0].style.filter = 'grayscale(100%)';"; // 注入 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript InjectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; wkUScript を返します。}
UILabel、UIButton などのその他の分類については、以下を参照してください。
https://github.com/GeLeis/App_NoirDemo
3番目の解決策:
画像処理は解決策 2 に似ています
が、Label、View などの色を 1 つずつ分類するのではなく、Color の分類を直接変更します。
+ (void)load { //关键メソッド交换 メソッド customMethod = class_getClassMethod([self class], @selector(gl_colorWithRed:green:blue:alpha:)); メソッド originMethod = class_getClassMethod([self クラス], @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 値 //白黒かどうか、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 これらの 3 つは、r、g、b の 3 色の表面知覚に対する人間の目の強さに従って計算されます CGFloat 輝度 = (赤 * 0.2126 + 0.7152 * green + 0.0722 * blue); return [self gl_colorWithRed:brightness green:brightness blue:brightness alpha:alpha]; } return [self gl_colorWithRed:red green:green blue:blue alpha:alpha]; }
オプション 4:
ランタイム メソッドではなく、グレー フィルターをビューに直接追加します。
//RGBA カラー値を取得します
CGFloat r,g,b,a;
[[UIColor lightGrayColor] getRed:&r green:&g blue:&b alpha:&a]; //
フィルター
ID を作成します 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:フィルター];
[UIColor lightGrayColor] の代わりに、r、g、b、および a の値を直接変更できます。
特定のコントローラーAだけなら設定するA.view.layer.filters = [NSArray arrayWithObject:filter];
だけ
もちろん、他のフィルターも使えます。
id cls = NSClassFromString(@"CAFilter");
id フィルター = [cls filterWithName:@"colorSaturate"];
[filter setValue:@(0) forKey:@"inputAmount"];
// window を設定します
self.window.layer.filters = [NSArray arrayWithObject:filter];
CAFilter は Apple のプライベート メソッドであり、拒否される可能性があるため、このメソッドは使用されません
最終アプローチ
クリック イベントを受信しないビューを追加する
@interface ZRLandlordHPGrayView : UIView
@終わり
@implementation ZRLandlordHPGrayView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{ 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; overlay.backgroundColor = [ UIColor grayColor] ; overlay.layer.compositingFilter = @"saturationBlendMode"; [superView addSubview:overlay];
[superView BringSubviewToFront:オーバーレイ];
} }
}
この方法は12以上しか対応しておらず、
うちのアプリを見てみると基本的に12以下はほとんどないので、最終的にこの方法にしました
その他の参考記事:
iOS インターフェース グレイイング ソリューション ディスカッションiOS でブラック マジックを使用してワンクリックでグローバル画像グレイイング ソリューションを実現する iOS 喪中モード
iOS APP インターフェース 白黒処理 (グレースケール処理) (喪日に備えて)