自定义 webview 键盘问题
Custom webview keyboard issues
所以从这个线程改编代码 UIKeyboardAppearance in UIWebView and TomSwift's 很棒的答案,我得到了大约 99% 的工作。
在 iOS 7 模拟器中,一切似乎都运行良好。然而在 iOS 8 中,当键盘第一次出现时,< > 完成栏是白色的。当我点击或 select 另一个输入时,它会更改为我指定的颜色。
我的问题是,如何防止和/或更改该白色部分?
其他线程中的所有代码都是相同的,除了我在 keyboardWillAppear 中这样调用的颜色。
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([[possibleFormView description] hasPrefix : @"<UIInputSetContainerView"]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
}
}
}
}
如有任何帮助,我们将不胜感激。
虽然让它正常工作会很好,但我决定采取完全放弃它的方法,而是使用点击关闭键盘。
我的印象是隐藏它也会隐藏自动更正栏。事实并非如此。
下面是我正在使用的完整代码。
键盘的最终颜色代码,由我的应用程序设置中的切换开关调用。
NSUserDefaults *darkDefaults = [NSUserDefaults standardUserDefaults];
BOOL darkOn = [darkDefaults boolForKey:@"darkKeyboard"];
if (darkOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
}
}
}
}
}
else{
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
}
隐藏键盘。在我的视图控制器的顶部调用(可能不是苹果安全的,但我不需要发布所以它对我有用):
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (CustomToolbar)
- (id)inputAccessoryView {
return nil;
}
@end
现在根据我的测试,我可以通过在 inputAccessoryView 部分绘制一个新的视图或工具栏来为其着色,但是用于关闭的点击会弄乱它,需要进行一些调整,但这不是正常的标准栏我正要去。好吧。
如果您想像我在 table 视图中所做的那样实现切换,我是这样做的。
- (id)init{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reloadTableView:)
name:NSUserDefaultsDidChangeNotification object:nil];
return [self initWithStyle:UITableViewStyleGrouped];
}
cellForRowAtIndexPath:
[cell.textLabel setText:@"Dark Keyboard"];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
darkKeyboard = [[UISwitch alloc] initWithFrame: CGRectMake(7, 0, 0, 0)];
cell.accessoryView = [[UIView alloc] initWithFrame:darkKeyboard.frame];
[cell.accessoryView addSubview:darkKeyboard];
[self.darkKeyboard addTarget:self action:@selector(updateSwitchAtIndexPath:) forControlEvents:UIControlEventValueChanged];
//On Color
darkKeyboard.onTintColor = [UIColor colorWithRed:0.204 green:0.667 blue:0.863 alpha:0.85];
//Off Color
darkKeyboard.backgroundColor = [UIColor colorWithRed:0.678 green:0.161 blue:0.188 alpha:0.75];
darkKeyboard.TintColor = [UIColor clearColor];
darkKeyboard.layer.cornerRadius = 16.0;
//Risize
darkKeyboard.transform = CGAffineTransformMakeScale(1.1, 1.1);
//User defaults
darkKeyboard.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"darkKeyboard"];
UIView *keyboard = [[UIView alloc] initWithFrame:cell.frame];
keyboard.backgroundColor = [UIColor colorWithRed:0.176 green:0.176 blue:0.176 alpha:1];
cell.backgroundView = keyboard;
didSelectRowAtIndexPath:
刚刚添加了一个 NSLog,这里什么都不需要。
- (void)updateSwitchAtIndexPath:(id)sender {
if (darkKeyboard){
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:self.darkKeyboard.on forKey:@"darkKeyboard"];
[userDefaults synchronize];
if ([darkKeyboard isOn]) {
[darkKeyboard setOn:YES animated:YES];
[self.tableView reloadData];
[[UIApplication sharedApplication] reloadInputViews];
} else {
[darkKeyboard setOn:NO animated:YES];
[self.tableView reloadData];
[[UIApplication sharedApplication] reloadInputViews];
}
}
}
希望这对某人有所帮助。
替代答案。
因此,无需尝试定义另一种颜色,只需使用提到的开关获得浅色或深色外观即可。我将它添加到我的 AppDelegate,(有些人不喜欢在这里添加东西,但是我的应用程序中有这么多视图,这是必须的)。
将此添加到 @interface AppDelegate ()
上方
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
完美运行。苹果可能不会接受,但我对此没兴趣。
现在适合那些不想创建切换键而只想使用深色键盘的人。
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
return UIKeyboardAppearanceDark;
}
@end
更新:
使用自定义颜色:在模拟器中从 iOS 7-8.2 测试。
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIPeripheralHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
//Setting custom color
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.50];
}
}
}
}
return UIKeyboardAppearanceDark;
}
else {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIPeripheralHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
//Clear color so it doesn't show when switching with toggle
peripheralView_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
return UIKeyboardAppearanceDefault;
}
}
@end
希望这对未来的 webview 开发人员有所帮助。
因此,随着 iOS 9+ 的出现,我发现它破坏了上述方法。但是通过一些修补和浏览一些观点,我想出了一个补充我已经在下面回答的内容。
现在我决定放弃自定义颜色的东西,我正在挖掘适合我的应用程序的黑色键盘。无论如何,这对我有用。在 9.1 sim 到 7 上测试。也在我的 6+ 运行 9.0.2.
//Keyboard setting
@interface UIWebBrowserView : UIView
@end
@interface UIWebBrowserView (UIWebBrowserView_Additions)
@end
@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (id)inputAccessoryView {
return nil;
}
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
@interface UITextInputTraits : UIWebBrowserView
@end
@interface UITextInputTraits (UIWebBrowserView)
@end
@implementation UITextInputTraits (UIWebBrowserView)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
我真的希望有人觉得这些答案有用:D
更新信息:
对完成栏很好奇,这就是这一切的开始。我重新启用它只是为了看看,发现它把它变成了黑色。不错的奖励,虽然我已经放弃它以使用滚动隐藏键盘。
更新 2015 年 12 月 19 日
所以我决定从 UIWebView 过渡到 WKWebView,结果发现两者之间显然有所不同。我设法让它再次工作。常规的 UIKeyboardAppearanceDark 调用会导致键盘比我喜欢的更透明。所以我根据自己的喜好修改了它。再一次,可能不是标准的做事方式,但我不在乎,反正它不会成为苹果。
所有内容仍在 AppDelegate 中。
//Removing the input bar above the keyboard.
@interface InputHider : NSObject @end
@implementation InputHider
-(id)inputAccessoryView{
return nil;
}
@end
@interface UIWebBrowserView : NSObject
@end
@interface NSObject (UIWebBrowserView_Additions)
@end
@implementation NSObject (UIWebBrowserView_Additions)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] ||
[possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
//Accessory bar color
if ([possibleFormView isKindOfClass:NSClassFromString(@"WKContentView")]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
[[UIInputViewContent_sub layer] setOpacity : 1.0];
UIInputViewContent_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
}
}
}
}
}
}
return UIKeyboardAppearanceDark;
}
else {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIKeyboard")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor clearColor];
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor clearColor];
//Accessory bar color
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIWebFormAccessory")]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
[[UIInputViewContent_sub layer] setOpacity : 1.0];
UIInputViewContent_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
}
}
return UIKeyboardAppearanceDefault;
}
}
@end
@interface UITextInputTraits : UIWebBrowserView
@end
@interface UITextInputTraits (UIWebBrowserView)
@end
@implementation UITextInputTraits (UIWebBrowserView)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
//Disables endDisablingInterfaceAutorotationAnimated error for keyboard
@interface UIWindow (UIWebBrowserView)
- (void)beginDisablingInterfaceAutorotation;
- (void)endDisablingInterfaceAutorotation;
@end
@implementation UIWindow (UIWebBrowserView)
- (void)beginDisablingInterfaceAutorotation {}
- (void)endDisablingInterfaceAutorotation{}
@end
我还没有像以前那样设法找到隐藏 inputAccessoryBar 的方法,但多亏了几个线程,我让它工作了。在我的视图控制器中,我调用:
-(void)removeInputAccessoryView {
UIView* subview;
for (UIView* view in webView.scrollView.subviews) {
if([[view.class description] hasPrefix:@"WKContent"])
subview = view;
}
if(subview == nil) return;
NSString* name = [NSString stringWithFormat:@"%@SwizzleHelper", subview.class.superclass];
Class newClass = NSClassFromString(name);
if(newClass == nil)
{
newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
if(!newClass) return;
Method method = class_getInstanceMethod([AppDelegate class], @selector(inputAccessoryView));
class_addMethod(newClass, @selector(inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method));
objc_registerClassPair(newClass);
}
object_setClass(subview, newClass);
}
然后在 viewDidLoad 中调用:
[self removeInputAccessoryView];
我计划再进行一些修改,但就目前而言,它可以满足我的需要。
WKWebView 键盘
这是一个使用 swizzling 的 WKWebView 解决方案,它很容易合并并适用于 iOS 9、10 和 11。只需创建一个名为 的新 class WKKeyboard 并添加以下代码:
WKKeyboard.h
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface WKKeyboard : NSObject
+ (void)setStyle:(UIKeyboardAppearance)style on:(WKWebView *)webView;
@end
WKKeyboard.m
#import "WKKeyboard.h"
#import <objc/runtime.h>
@implementation WKKeyboard
// Allows the changing of keyboard styles
static UIKeyboardAppearance keyboardStyle;
// Leave this as an instance method
- (UIKeyboardAppearance)keyboardAppearance {
return keyboardStyle;
}
// This can be a class method
+ (void)setStyle:(UIKeyboardAppearance)style on:(WKWebView *)webView {
for (UIView *view in [[webView scrollView] subviews]) {
if([[view.class description] containsString:@"WKContent"]) {
UIView *content = view;
NSString *className = [NSString stringWithFormat:@"%@_%@",[[content class] superclass],[self class]];
Class newClass = NSClassFromString(className);
if (!newClass) {
newClass = objc_allocateClassPair([content class], [className cStringUsingEncoding:NSASCIIStringEncoding], 0);
Method method = class_getInstanceMethod([WKKeyboard class], @selector(keyboardAppearance));
class_addMethod(newClass, @selector(keyboardAppearance), method_getImplementation(method), method_getTypeEncoding(method));
objc_registerClassPair(newClass);
}
object_setClass(content, newClass);
keyboardStyle = style;
return;
}
}
}
@end
用法
// The WKWebView you want to change the keyboard on
WKWebView *webView = [WKWebView alloc] init];
// Then just call the class method with the style and webview
[WKKeyboard setStyle:UIKeyboardAppearanceDark on:webView];
希望这对某些人有所帮助,这样您就可以有选择地更改单个 WKWebView 的外观,而不是全部!
像下面这样扩展 UIWebBrowserView,将使您的应用程序被应用程序商店禁止。
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
return UIKeyboardAppearanceDark;
}
@end
因此,您需要在运行时扩展 Web 视图。
以下代码以与 iOS12 兼容且不会被 Apple 拒绝的方式实现此功能。
对于此示例,我使用全局 _s_isDark
来确定所需的键盘样式。
@implementation UIWebView (KeyboardAppearanceAndAccessoryHiding)
- (void) setModifiedWebviewView {
// find the UIWebBrowserView
for (UIView *browserView in self.scrollView.subviews) {
if ([NSStringFromClass([browserView class]) hasPrefix:@"UIWebBrowserView"]) {
// Allocate a UIWebBrowserView subclass
Class newClass = objc_allocateClassPair([browserView class], "UIWebBrowserModified", 0);
// Add a nil method to hide the accessory view
IMP nilImp = [self methodForSelector:@selector(methodReturningNil)];
class_addMethod(newClass, @selector(inputAccessoryView), nilImp, "@@:");
// Add a method to set dark or light keyboard
Method m = class_getInstanceMethod([self class], @selector(keyboardAppearance));
IMP keyboardAppearanceImp = method_getImplementation(m);
const char* typeEncoding = method_getTypeEncoding(m);
class_addMethod(newClass, @selector(keyboardAppearance), keyboardAppearanceImp, typeEncoding);
// Replace the class of the UIWebBrowserView with the new subclass
objc_registerClassPair(newClass);
object_setClass(browserView, newClass);
break;
}
}
}
- (id)methodReturningNil {
return nil;
}
- (UIKeyboardAppearance)keyboardAppearance {
return _s_isDark ? UIKeyboardAppearanceDark : UIKeyboardAppearanceLight;
}
@end
// We also need to extend the text input traits
@interface UITextInputTraits
@end
@interface UITextInputTraits (ForWebViewFields)
@end
@implementation UITextInputTraits (ForWebViewFields)
- (UIKeyboardAppearance)keyboardAppearance {
return _s_isDark ? UIKeyboardAppearanceDark : UIKeyboardAppearanceLight;
}
@end
更新:自 2020 年 2 月起,扩展 UITextInputTraits 也会让您被禁止进入 App Store(ITMS-90338:非 public API 用法)。我不确定是否需要继承 UITextInputTraits。
Swift 版本的 答案。它对我很有效。方法混合是一种方法。
class WKKeybaord: NSObject {
static var keyboardStyle: UIKeyboardAppearance = .default
@objc func keyboardAppearance() -> UIKeyboardAppearance {
return WKKeybaord.keyboardStyle
}
class func setStyle(with style: UIKeyboardAppearance, on webView: WKWebView) {
for view in webView.scrollView.subviews {
if view.self.description.contains("WKContent") {
let content = view
var className: String? = nil
if let superclass = content.self.superclass {
className = "\(superclass)_\(type(of: self))"
}
var newClass: AnyClass? = NSClassFromString(className ?? "")
if newClass == nil {
newClass = objc_allocateClassPair(object_getClass(content), className ?? "", 0)
if let method = class_getInstanceMethod(WKKeybaord.self, #selector(self.keyboardAppearance)) {
class_addMethod(newClass, #selector(self.keyboardAppearance), method_getImplementation(method), method_getTypeEncoding(method))
objc_registerClassPair(newClass!)
}
}
object_setClass(content, newClass!)
keyboardStyle = style
return
}
}
}
}
所以从这个线程改编代码 UIKeyboardAppearance in UIWebView and TomSwift's 很棒的答案,我得到了大约 99% 的工作。
在 iOS 7 模拟器中,一切似乎都运行良好。然而在 iOS 8 中,当键盘第一次出现时,< > 完成栏是白色的。当我点击或 select 另一个输入时,它会更改为我指定的颜色。
我的问题是,如何防止和/或更改该白色部分?
其他线程中的所有代码都是相同的,除了我在 keyboardWillAppear 中这样调用的颜色。
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([[possibleFormView description] hasPrefix : @"<UIInputSetContainerView"]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
}
}
}
}
如有任何帮助,我们将不胜感激。
虽然让它正常工作会很好,但我决定采取完全放弃它的方法,而是使用点击关闭键盘。
我的印象是隐藏它也会隐藏自动更正栏。事实并非如此。
下面是我正在使用的完整代码。
键盘的最终颜色代码,由我的应用程序设置中的切换开关调用。
NSUserDefaults *darkDefaults = [NSUserDefaults standardUserDefaults];
BOOL darkOn = [darkDefaults boolForKey:@"darkKeyboard"];
if (darkOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.75];
}
}
}
}
}
else{
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
}
隐藏键盘。在我的视图控制器的顶部调用(可能不是苹果安全的,但我不需要发布所以它对我有用):
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (CustomToolbar)
- (id)inputAccessoryView {
return nil;
}
@end
现在根据我的测试,我可以通过在 inputAccessoryView 部分绘制一个新的视图或工具栏来为其着色,但是用于关闭的点击会弄乱它,需要进行一些调整,但这不是正常的标准栏我正要去。好吧。
如果您想像我在 table 视图中所做的那样实现切换,我是这样做的。
- (id)init{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reloadTableView:)
name:NSUserDefaultsDidChangeNotification object:nil];
return [self initWithStyle:UITableViewStyleGrouped];
}
cellForRowAtIndexPath:
[cell.textLabel setText:@"Dark Keyboard"];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
darkKeyboard = [[UISwitch alloc] initWithFrame: CGRectMake(7, 0, 0, 0)];
cell.accessoryView = [[UIView alloc] initWithFrame:darkKeyboard.frame];
[cell.accessoryView addSubview:darkKeyboard];
[self.darkKeyboard addTarget:self action:@selector(updateSwitchAtIndexPath:) forControlEvents:UIControlEventValueChanged];
//On Color
darkKeyboard.onTintColor = [UIColor colorWithRed:0.204 green:0.667 blue:0.863 alpha:0.85];
//Off Color
darkKeyboard.backgroundColor = [UIColor colorWithRed:0.678 green:0.161 blue:0.188 alpha:0.75];
darkKeyboard.TintColor = [UIColor clearColor];
darkKeyboard.layer.cornerRadius = 16.0;
//Risize
darkKeyboard.transform = CGAffineTransformMakeScale(1.1, 1.1);
//User defaults
darkKeyboard.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"darkKeyboard"];
UIView *keyboard = [[UIView alloc] initWithFrame:cell.frame];
keyboard.backgroundColor = [UIColor colorWithRed:0.176 green:0.176 blue:0.176 alpha:1];
cell.backgroundView = keyboard;
didSelectRowAtIndexPath: 刚刚添加了一个 NSLog,这里什么都不需要。
- (void)updateSwitchAtIndexPath:(id)sender {
if (darkKeyboard){
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:self.darkKeyboard.on forKey:@"darkKeyboard"];
[userDefaults synchronize];
if ([darkKeyboard isOn]) {
[darkKeyboard setOn:YES animated:YES];
[self.tableView reloadData];
[[UIApplication sharedApplication] reloadInputViews];
} else {
[darkKeyboard setOn:NO animated:YES];
[self.tableView reloadData];
[[UIApplication sharedApplication] reloadInputViews];
}
}
}
希望这对某人有所帮助。
替代答案。
因此,无需尝试定义另一种颜色,只需使用提到的开关获得浅色或深色外观即可。我将它添加到我的 AppDelegate,(有些人不喜欢在这里添加东西,但是我的应用程序中有这么多视图,这是必须的)。
将此添加到 @interface AppDelegate ()
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
完美运行。苹果可能不会接受,但我对此没兴趣。
现在适合那些不想创建切换键而只想使用深色键盘的人。
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
return UIKeyboardAppearanceDark;
}
@end
更新: 使用自定义颜色:在模拟器中从 iOS 7-8.2 测试。
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIPeripheralHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
//Setting custom color
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:0.50];
}
}
}
}
return UIKeyboardAppearanceDark;
}
else {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIPeripheralHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
//Clear color so it doesn't show when switching with toggle
peripheralView_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
return UIKeyboardAppearanceDefault;
}
}
@end
希望这对未来的 webview 开发人员有所帮助。
因此,随着 iOS 9+ 的出现,我发现它破坏了上述方法。但是通过一些修补和浏览一些观点,我想出了一个补充我已经在下面回答的内容。
现在我决定放弃自定义颜色的东西,我正在挖掘适合我的应用程序的黑色键盘。无论如何,这对我有用。在 9.1 sim 到 7 上测试。也在我的 6+ 运行 9.0.2.
//Keyboard setting
@interface UIWebBrowserView : UIView
@end
@interface UIWebBrowserView (UIWebBrowserView_Additions)
@end
@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (id)inputAccessoryView {
return nil;
}
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
@interface UITextInputTraits : UIWebBrowserView
@end
@interface UITextInputTraits (UIWebBrowserView)
@end
@implementation UITextInputTraits (UIWebBrowserView)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
我真的希望有人觉得这些答案有用:D
更新信息: 对完成栏很好奇,这就是这一切的开始。我重新启用它只是为了看看,发现它把它变成了黑色。不错的奖励,虽然我已经放弃它以使用滚动隐藏键盘。
更新 2015 年 12 月 19 日 所以我决定从 UIWebView 过渡到 WKWebView,结果发现两者之间显然有所不同。我设法让它再次工作。常规的 UIKeyboardAppearanceDark 调用会导致键盘比我喜欢的更透明。所以我根据自己的喜好修改了它。再一次,可能不是标准的做事方式,但我不在乎,反正它不会成为苹果。
所有内容仍在 AppDelegate 中。
//Removing the input bar above the keyboard.
@interface InputHider : NSObject @end
@implementation InputHider
-(id)inputAccessoryView{
return nil;
}
@end
@interface UIWebBrowserView : NSObject
@end
@interface NSObject (UIWebBrowserView_Additions)
@end
@implementation NSObject (UIWebBrowserView_Additions)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] ||
[possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetHostView")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
//Accessory bar color
if ([possibleFormView isKindOfClass:NSClassFromString(@"WKContentView")]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
[[UIInputViewContent_sub layer] setOpacity : 1.0];
UIInputViewContent_sub.backgroundColor = [UIColor colorWithRed:0.271 green:0.271 blue:0.271 alpha:1.0];
}
}
}
}
}
}
return UIKeyboardAppearanceDark;
}
else {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIInputSetContainerView")] || [possibleFormView isKindOfClass:NSClassFromString(@"UIKeyboard")]) {
for (UIView* peripheralView in possibleFormView.subviews) {
peripheralView.backgroundColor = [UIColor clearColor];
//Keyboard background
for (UIView* peripheralView_sub in peripheralView.subviews) {
peripheralView_sub.backgroundColor = [UIColor clearColor];
//Accessory bar color
if ([possibleFormView isKindOfClass:NSClassFromString(@"UIWebFormAccessory")]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
[[UIInputViewContent_sub layer] setOpacity : 1.0];
UIInputViewContent_sub.backgroundColor = [UIColor clearColor];
}
}
}
}
}
}
return UIKeyboardAppearanceDefault;
}
}
@end
@interface UITextInputTraits : UIWebBrowserView
@end
@interface UITextInputTraits (UIWebBrowserView)
@end
@implementation UITextInputTraits (UIWebBrowserView)
- (UIKeyboardAppearance) keyboardAppearance{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"darkKeyboard"];
if (switchOn) {
return UIKeyboardAppearanceDark;
}
else {
return UIKeyboardAppearanceDefault;
}
}
@end
//Disables endDisablingInterfaceAutorotationAnimated error for keyboard
@interface UIWindow (UIWebBrowserView)
- (void)beginDisablingInterfaceAutorotation;
- (void)endDisablingInterfaceAutorotation;
@end
@implementation UIWindow (UIWebBrowserView)
- (void)beginDisablingInterfaceAutorotation {}
- (void)endDisablingInterfaceAutorotation{}
@end
我还没有像以前那样设法找到隐藏 inputAccessoryBar 的方法,但多亏了几个线程,我让它工作了。在我的视图控制器中,我调用:
-(void)removeInputAccessoryView {
UIView* subview;
for (UIView* view in webView.scrollView.subviews) {
if([[view.class description] hasPrefix:@"WKContent"])
subview = view;
}
if(subview == nil) return;
NSString* name = [NSString stringWithFormat:@"%@SwizzleHelper", subview.class.superclass];
Class newClass = NSClassFromString(name);
if(newClass == nil)
{
newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
if(!newClass) return;
Method method = class_getInstanceMethod([AppDelegate class], @selector(inputAccessoryView));
class_addMethod(newClass, @selector(inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method));
objc_registerClassPair(newClass);
}
object_setClass(subview, newClass);
}
然后在 viewDidLoad 中调用:
[self removeInputAccessoryView];
我计划再进行一些修改,但就目前而言,它可以满足我的需要。
WKWebView 键盘
这是一个使用 swizzling 的 WKWebView 解决方案,它很容易合并并适用于 iOS 9、10 和 11。只需创建一个名为 的新 class WKKeyboard 并添加以下代码:
WKKeyboard.h
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface WKKeyboard : NSObject
+ (void)setStyle:(UIKeyboardAppearance)style on:(WKWebView *)webView;
@end
WKKeyboard.m
#import "WKKeyboard.h"
#import <objc/runtime.h>
@implementation WKKeyboard
// Allows the changing of keyboard styles
static UIKeyboardAppearance keyboardStyle;
// Leave this as an instance method
- (UIKeyboardAppearance)keyboardAppearance {
return keyboardStyle;
}
// This can be a class method
+ (void)setStyle:(UIKeyboardAppearance)style on:(WKWebView *)webView {
for (UIView *view in [[webView scrollView] subviews]) {
if([[view.class description] containsString:@"WKContent"]) {
UIView *content = view;
NSString *className = [NSString stringWithFormat:@"%@_%@",[[content class] superclass],[self class]];
Class newClass = NSClassFromString(className);
if (!newClass) {
newClass = objc_allocateClassPair([content class], [className cStringUsingEncoding:NSASCIIStringEncoding], 0);
Method method = class_getInstanceMethod([WKKeyboard class], @selector(keyboardAppearance));
class_addMethod(newClass, @selector(keyboardAppearance), method_getImplementation(method), method_getTypeEncoding(method));
objc_registerClassPair(newClass);
}
object_setClass(content, newClass);
keyboardStyle = style;
return;
}
}
}
@end
用法
// The WKWebView you want to change the keyboard on
WKWebView *webView = [WKWebView alloc] init];
// Then just call the class method with the style and webview
[WKKeyboard setStyle:UIKeyboardAppearanceDark on:webView];
希望这对某些人有所帮助,这样您就可以有选择地更改单个 WKWebView 的外观,而不是全部!
像下面这样扩展 UIWebBrowserView,将使您的应用程序被应用程序商店禁止。
@interface UIWebBrowserView : UIView
@end
@implementation UIWebBrowserView (KeyboardSwitch)
- (UIKeyboardAppearance) keyboardAppearance{
return UIKeyboardAppearanceDark;
}
@end
因此,您需要在运行时扩展 Web 视图。
以下代码以与 iOS12 兼容且不会被 Apple 拒绝的方式实现此功能。
对于此示例,我使用全局 _s_isDark
来确定所需的键盘样式。
@implementation UIWebView (KeyboardAppearanceAndAccessoryHiding)
- (void) setModifiedWebviewView {
// find the UIWebBrowserView
for (UIView *browserView in self.scrollView.subviews) {
if ([NSStringFromClass([browserView class]) hasPrefix:@"UIWebBrowserView"]) {
// Allocate a UIWebBrowserView subclass
Class newClass = objc_allocateClassPair([browserView class], "UIWebBrowserModified", 0);
// Add a nil method to hide the accessory view
IMP nilImp = [self methodForSelector:@selector(methodReturningNil)];
class_addMethod(newClass, @selector(inputAccessoryView), nilImp, "@@:");
// Add a method to set dark or light keyboard
Method m = class_getInstanceMethod([self class], @selector(keyboardAppearance));
IMP keyboardAppearanceImp = method_getImplementation(m);
const char* typeEncoding = method_getTypeEncoding(m);
class_addMethod(newClass, @selector(keyboardAppearance), keyboardAppearanceImp, typeEncoding);
// Replace the class of the UIWebBrowserView with the new subclass
objc_registerClassPair(newClass);
object_setClass(browserView, newClass);
break;
}
}
}
- (id)methodReturningNil {
return nil;
}
- (UIKeyboardAppearance)keyboardAppearance {
return _s_isDark ? UIKeyboardAppearanceDark : UIKeyboardAppearanceLight;
}
@end
// We also need to extend the text input traits
@interface UITextInputTraits
@end
@interface UITextInputTraits (ForWebViewFields)
@end
@implementation UITextInputTraits (ForWebViewFields)
- (UIKeyboardAppearance)keyboardAppearance {
return _s_isDark ? UIKeyboardAppearanceDark : UIKeyboardAppearanceLight;
}
@end
更新:自 2020 年 2 月起,扩展 UITextInputTraits 也会让您被禁止进入 App Store(ITMS-90338:非 public API 用法)。我不确定是否需要继承 UITextInputTraits。
Swift 版本的
class WKKeybaord: NSObject {
static var keyboardStyle: UIKeyboardAppearance = .default
@objc func keyboardAppearance() -> UIKeyboardAppearance {
return WKKeybaord.keyboardStyle
}
class func setStyle(with style: UIKeyboardAppearance, on webView: WKWebView) {
for view in webView.scrollView.subviews {
if view.self.description.contains("WKContent") {
let content = view
var className: String? = nil
if let superclass = content.self.superclass {
className = "\(superclass)_\(type(of: self))"
}
var newClass: AnyClass? = NSClassFromString(className ?? "")
if newClass == nil {
newClass = objc_allocateClassPair(object_getClass(content), className ?? "", 0)
if let method = class_getInstanceMethod(WKKeybaord.self, #selector(self.keyboardAppearance)) {
class_addMethod(newClass, #selector(self.keyboardAppearance), method_getImplementation(method), method_getTypeEncoding(method))
objc_registerClassPair(newClass!)
}
}
object_setClass(content, newClass!)
keyboardStyle = style
return
}
}
}
}