如何改变WKWebView中的文本选择颜色?
How to change the text selection color in WKWebView?
我正在尝试更改 WKWebView
中的文本选择颜色。我尝试了几乎所有我能找到的为 UIWebView
/WKWebView
提出的解决方案。
更改色调无效。为 ::selection
、-webkit-tap-highlight-color
标签应用 css 均无效。
它总是蓝色的。可以改吗?
这是它的示例代码。
function highlight(colour) {
var range, sel;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}}
通过Objective-C代码调用此方法
[webView stringByEvaluatingJavaScriptFromString:@"highlight('#ff0')"];
这是我在 private WebKit API hacky swizzling 上的截图,显然 不符合 AppStore 应用程序的条件。 Apple 正好为它提供了很多开源代码:
https://opensource.apple.com/source/WebKit2/WebKit2-7601.1.46.9/UIProcess/ios/WKContentViewInteraction.h.auto.html
https://opensource.apple.com/source/WebKit2/WebKit2-7601.1.46.9/UIProcess/ios/WKContentViewInteraction.mm.auto.html
因此 html 内容的实际选择突出显示分两个阶段进行。直到在触摸屏上按住点击 private class UIWKSelectionView
显示。亮点恰好是它的tintView
属性。每个 tintView
getter 调用都会生成一个新的 UIView
实例,并以高亮颜色作为背景。所以覆盖需要在每次访问后发生。
在第二阶段(用户释放点击后)所选范围由 private class UIWebTextRangeView
表示。带点的文本垂直标记为 UIWebDragDotView
。突出显示发生在 updateRectViews
方法中,需要在进行颜色覆盖之前调用该方法。
最终解决方案是 validated for iOS 8 - 11,一旦颜色被覆盖,它将影响所有 WKWebView
实例。原始高亮颜色在 UIWKSelectionView
& UIWebTextRangeView
中硬编码并通过 UIKit 私有方法 +[UIColor selectionHighlightColor]
获取,得到 RGBA 0 0.33 0.65 0.2
.
实际代码(我选择 obj-c
是为了方便 swizzling 但这也可以在 Swift
中完成):
#import "ViewController.h"
#import <objc/runtime.h>
@import WebKit;
static IMP __original_Method_IMP_tintView;
static IMP __original_Method_IMP_updateRectViews;
//UIWebTextRangeView
void replacement_updateRectViews(UIView* self, SEL _cmd)
{
((void(*)(id,SEL))__original_Method_IMP_updateRectViews)(self, _cmd);
for (UIView* view in self.subviews) {
//isMemberOfClass would be used instead to filter out UIWebDragDotView if its color is meant to be unchanged
if ([view isKindOfClass:NSClassFromString(@"UIWebDragDotView")]) {
[view setValue:UIColor.redColor forKey:@"m_selectionBarColor"];
} else {
//These are UIView*
view.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.2];
}
}
}
//UIWKSelectionView
UIView* replacement_tintView(id self, SEL _cmd)
{
UIView* tintView = ((UIView*(*)(id,SEL))__original_Method_IMP_tintView)(self, _cmd);
tintView.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.2];
return tintView;
}
@interface ViewController ()
@end
@implementation ViewController
+ (void)load {
__original_Method_IMP_tintView = method_setImplementation(class_getInstanceMethod(NSClassFromString(@"UIWKSelectionView"),NSSelectorFromString(@"tintView")), (IMP)replacement_tintView);
__original_Method_IMP_updateRectViews = method_setImplementation(class_getInstanceMethod(NSClassFromString(@"UIWebTextRangeView"),NSSelectorFromString(@"updateRectViews")), (IMP)replacement_updateRectViews);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view = [WKWebView new];
[(WKWebView*)self.view loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://whosebug.com/"]]];
}
@end
从 iOS 13 开始,设置 WKWebView 的 tintColor
属性 也会更改选择颜色(和插入符号颜色)。
WKWebView *webView = ...
webView.tintColor = UIColor.redColor;
额外提示:如果您的应用程序支持深色模式,但出于某种原因 WKWebView 内容必须为浅色模式,您可以强制包含 WKWebView 的整个视图控制器具有浅色模式特征,或者您可以做:
if (@available(iOS 13.0, *)) {
webView.tintColor = [webView.tintColor resolvedColorWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]];
}
这确保选择和插入符号颜色在 html
中的 "light" 内容中可见
我正在尝试更改 WKWebView
中的文本选择颜色。我尝试了几乎所有我能找到的为 UIWebView
/WKWebView
提出的解决方案。
更改色调无效。为 ::selection
、-webkit-tap-highlight-color
标签应用 css 均无效。
它总是蓝色的。可以改吗?
这是它的示例代码。
function highlight(colour) {
var range, sel;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}}
通过Objective-C代码调用此方法
[webView stringByEvaluatingJavaScriptFromString:@"highlight('#ff0')"];
这是我在 private WebKit API hacky swizzling 上的截图,显然 不符合 AppStore 应用程序的条件。 Apple 正好为它提供了很多开源代码: https://opensource.apple.com/source/WebKit2/WebKit2-7601.1.46.9/UIProcess/ios/WKContentViewInteraction.h.auto.html https://opensource.apple.com/source/WebKit2/WebKit2-7601.1.46.9/UIProcess/ios/WKContentViewInteraction.mm.auto.html
因此 html 内容的实际选择突出显示分两个阶段进行。直到在触摸屏上按住点击 private class UIWKSelectionView
显示。亮点恰好是它的tintView
属性。每个 tintView
getter 调用都会生成一个新的 UIView
实例,并以高亮颜色作为背景。所以覆盖需要在每次访问后发生。
在第二阶段(用户释放点击后)所选范围由 private class UIWebTextRangeView
表示。带点的文本垂直标记为 UIWebDragDotView
。突出显示发生在 updateRectViews
方法中,需要在进行颜色覆盖之前调用该方法。
最终解决方案是 validated for iOS 8 - 11,一旦颜色被覆盖,它将影响所有 WKWebView
实例。原始高亮颜色在 UIWKSelectionView
& UIWebTextRangeView
中硬编码并通过 UIKit 私有方法 +[UIColor selectionHighlightColor]
获取,得到 RGBA 0 0.33 0.65 0.2
.
实际代码(我选择 obj-c
是为了方便 swizzling 但这也可以在 Swift
中完成):
#import "ViewController.h"
#import <objc/runtime.h>
@import WebKit;
static IMP __original_Method_IMP_tintView;
static IMP __original_Method_IMP_updateRectViews;
//UIWebTextRangeView
void replacement_updateRectViews(UIView* self, SEL _cmd)
{
((void(*)(id,SEL))__original_Method_IMP_updateRectViews)(self, _cmd);
for (UIView* view in self.subviews) {
//isMemberOfClass would be used instead to filter out UIWebDragDotView if its color is meant to be unchanged
if ([view isKindOfClass:NSClassFromString(@"UIWebDragDotView")]) {
[view setValue:UIColor.redColor forKey:@"m_selectionBarColor"];
} else {
//These are UIView*
view.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.2];
}
}
}
//UIWKSelectionView
UIView* replacement_tintView(id self, SEL _cmd)
{
UIView* tintView = ((UIView*(*)(id,SEL))__original_Method_IMP_tintView)(self, _cmd);
tintView.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.2];
return tintView;
}
@interface ViewController ()
@end
@implementation ViewController
+ (void)load {
__original_Method_IMP_tintView = method_setImplementation(class_getInstanceMethod(NSClassFromString(@"UIWKSelectionView"),NSSelectorFromString(@"tintView")), (IMP)replacement_tintView);
__original_Method_IMP_updateRectViews = method_setImplementation(class_getInstanceMethod(NSClassFromString(@"UIWebTextRangeView"),NSSelectorFromString(@"updateRectViews")), (IMP)replacement_updateRectViews);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view = [WKWebView new];
[(WKWebView*)self.view loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://whosebug.com/"]]];
}
@end
从 iOS 13 开始,设置 WKWebView 的 tintColor
属性 也会更改选择颜色(和插入符号颜色)。
WKWebView *webView = ...
webView.tintColor = UIColor.redColor;
额外提示:如果您的应用程序支持深色模式,但出于某种原因 WKWebView 内容必须为浅色模式,您可以强制包含 WKWebView 的整个视图控制器具有浅色模式特征,或者您可以做:
if (@available(iOS 13.0, *)) {
webView.tintColor = [webView.tintColor resolvedColorWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]];
}
这确保选择和插入符号颜色在 html
中的 "light" 内容中可见