Advertisement
Guest User

Untitled

a guest
Feb 20th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.75 KB | None | 0 0
  1. /*
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9.  
  10. http://www.apache.org/licenses/LICENSE-2.0
  11.  
  12. Unless required by applicable law or agreed to in writing,
  13. software distributed under the License is distributed on an
  14. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. KIND, either express or implied. See the License for the
  16. specific language governing permissions and limitations
  17. under the License.
  18. */
  19.  
  20. #import "CDVKeyboard.h"
  21. #import <Cordova/CDVAvailability.h>
  22. #import <objc/runtime.h>
  23.  
  24. #ifndef __CORDOVA_3_2_0
  25. #warning "The keyboard plugin is only supported in Cordova 3.2 or greater, it may not work properly in an older version. If you do use this plugin in an older version, make sure the HideKeyboardFormAccessoryBar and KeyboardShrinksView preference values are false."
  26. #endif
  27.  
  28. @interface CDVKeyboard () <UIScrollViewDelegate>
  29.  
  30. @property (nonatomic, readwrite, assign) BOOL keyboardIsVisible;
  31.  
  32. @end
  33.  
  34. @implementation CDVKeyboard
  35.  
  36. - (id)settingForKey:(NSString*)key
  37. {
  38. return [self.commandDelegate.settings objectForKey:[key lowercaseString]];
  39. }
  40.  
  41. #pragma mark Initialize
  42.  
  43. - (void)pluginInitialize
  44. {
  45. NSString* setting = nil;
  46.  
  47. setting = @"HideKeyboardFormAccessoryBar";
  48. if ([self settingForKey:setting]) {
  49. self.hideFormAccessoryBar = [(NSNumber*)[self settingForKey:setting] boolValue];
  50. }
  51.  
  52. setting = @"KeyboardShrinksView";
  53. if ([self settingForKey:setting]) {
  54. self.shrinkView = [(NSNumber*)[self settingForKey:setting] boolValue];
  55. }
  56.  
  57. setting = @"DisableScrollingWhenKeyboardShrinksView";
  58. if ([self settingForKey:setting]) {
  59. self.disableScrollingInShrinkView = [(NSNumber*)[self settingForKey:setting] boolValue];
  60. }
  61.  
  62. NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
  63. __weak CDVKeyboard* weakSelf = self;
  64.  
  65. _keyboardShowObserver = [nc addObserverForName:UIKeyboardDidShowNotification
  66. object:nil
  67. queue:[NSOperationQueue mainQueue]
  68. usingBlock:^(NSNotification* notification) {
  69.  
  70. [self.webView.scrollView setScrollEnabled:NO];
  71. NSLog(@"process _keyboardShowObserver");
  72. [weakSelf.commandDelegate evalJs:@"Keyboard.fireOnShow();"];
  73. }];
  74.  
  75.  
  76. _keyboardHideObserver = [nc addObserverForName:UIKeyboardDidHideNotification
  77. object:nil
  78. queue:[NSOperationQueue mainQueue]
  79. usingBlock:^(NSNotification* notification) {
  80. [weakSelf.commandDelegate evalJs:@"Keyboard.fireOnHide();"];
  81. }];
  82.  
  83. _keyboardWillShowObserver = [nc addObserverForName:UIKeyboardWillShowNotification
  84. object:nil
  85. queue:[NSOperationQueue mainQueue]
  86. usingBlock:^(NSNotification* notification) {
  87.  
  88. CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
  89. int height = MIN(keyboardSize.height,keyboardSize.width);
  90. UIEdgeInsets insets = self.webView.scrollView.contentInset;
  91. insets.bottom = height;
  92. self.webView.scrollView.contentInset = insets;
  93. [weakSelf.commandDelegate evalJs:@"Keyboard.fireOnShowing();"];
  94. weakSelf.keyboardIsVisible = YES;
  95. }];
  96. _keyboardWillHideObserver = [nc addObserverForName:UIKeyboardWillHideNotification
  97. object:nil
  98. queue:[NSOperationQueue mainQueue]
  99. usingBlock:^(NSNotification* notification) {
  100. [self.webView.scrollView setScrollEnabled:YES];
  101. self.webView.scrollView.contentInset = UIEdgeInsetsZero;
  102. [weakSelf.commandDelegate evalJs:@"Keyboard.fireOnHiding();"];
  103. weakSelf.keyboardIsVisible = NO;
  104. }];
  105.  
  106. _shrinkViewKeyboardWillChangeFrameObserver = [nc addObserverForName:UIKeyboardWillChangeFrameNotification
  107. object:nil
  108. queue:[NSOperationQueue mainQueue]
  109. usingBlock:^(NSNotification* notification) {
  110. NSLog(@"process _keyboardShowObserver");
  111. [weakSelf performSelector:@selector(shrinkViewKeyboardWillChangeFrame:) withObject:notification afterDelay:0];
  112. CGRect screen = [[UIScreen mainScreen] bounds];
  113. CGRect keyboard = ((NSValue*)notification.userInfo[@"UIKeyboardFrameEndUserInfoKey"]).CGRectValue;
  114. CGRect intersection = CGRectIntersection(screen, keyboard);
  115. CGFloat height = MIN(intersection.size.width, intersection.size.height);
  116. [weakSelf.commandDelegate evalJs: [NSString stringWithFormat:@"cordova.fireWindowEvent('keyboardHeightWillChange', { 'keyboardHeight': %f })", height]];
  117. }];
  118.  
  119. self.webView.scrollView.delegate = self;
  120. }
  121.  
  122. #pragma mark HideFormAccessoryBar
  123.  
  124. static IMP UIOriginalImp;
  125. static IMP WKOriginalImp;
  126.  
  127. - (void)setHideFormAccessoryBar:(BOOL)hideFormAccessoryBar
  128. {
  129. if (hideFormAccessoryBar == _hideFormAccessoryBar) {
  130. return;
  131. }
  132.  
  133. NSString* UIClassString = [@[@"UI", @"Web", @"Browser", @"View"] componentsJoinedByString:@""];
  134. NSString* WKClassString = [@[@"WK", @"Content", @"View"] componentsJoinedByString:@""];
  135.  
  136. Method UIMethod = class_getInstanceMethod(NSClassFromString(UIClassString), @selector(inputAccessoryView));
  137. Method WKMethod = class_getInstanceMethod(NSClassFromString(WKClassString), @selector(inputAccessoryView));
  138.  
  139. if (hideFormAccessoryBar) {
  140. UIOriginalImp = method_getImplementation(UIMethod);
  141. WKOriginalImp = method_getImplementation(WKMethod);
  142.  
  143. IMP newImp = imp_implementationWithBlock(^(id _s) {
  144. return nil;
  145. });
  146.  
  147. method_setImplementation(UIMethod, newImp);
  148. method_setImplementation(WKMethod, newImp);
  149. } else {
  150. method_setImplementation(UIMethod, UIOriginalImp);
  151. method_setImplementation(WKMethod, WKOriginalImp);
  152. }
  153.  
  154. _hideFormAccessoryBar = hideFormAccessoryBar;
  155. }
  156.  
  157. #pragma mark KeyboardShrinksView
  158.  
  159. - (void)setShrinkView:(BOOL)shrinkView
  160. {
  161. // Remove WKWebView's keyboard observers when using shrinkView
  162. // They've caused several issues with the plugin (#32, #55, #64)
  163. // Even if you later set shrinkView to false, the observers will not be added back
  164. NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
  165. if ([self.webView isKindOfClass:NSClassFromString(@"WKWebView")]) {
  166. [nc removeObserver:self.webView name:UIKeyboardWillHideNotification object:nil];
  167. [nc removeObserver:self.webView name:UIKeyboardWillShowNotification object:nil];
  168. [nc removeObserver:self.webView name:UIKeyboardWillChangeFrameNotification object:nil];
  169. [nc removeObserver:self.webView name:UIKeyboardDidChangeFrameNotification object:nil];
  170. }
  171. _shrinkView = shrinkView;
  172. }
  173.  
  174. - (void)shrinkViewKeyboardWillChangeFrame:(NSNotification*)notif
  175. {
  176. // No-op on iOS 7.0. It already resizes webview by default, and this plugin is causing layout issues
  177. // with fixed position elements. We possibly should attempt to implement shrinkview = false on iOS7.0.
  178. // iOS 7.1+ behave the same way as iOS 6
  179. if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_1 && NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
  180. return;
  181. }
  182.  
  183. // If the view is not visible, we should do nothing. E.g. if the inappbrowser is open.
  184. if (!(self.viewController.isViewLoaded && self.viewController.view.window)) {
  185. return;
  186. }
  187.  
  188. self.webView.scrollView.scrollEnabled = YES;
  189.  
  190. CGRect screen = [[UIScreen mainScreen] bounds];
  191. CGRect statusBar = [[UIApplication sharedApplication] statusBarFrame];
  192. CGRect keyboard = ((NSValue*)notif.userInfo[@"UIKeyboardFrameEndUserInfoKey"]).CGRectValue;
  193.  
  194. // Work within the webview's coordinate system
  195. keyboard = [self.webView convertRect:keyboard fromView:nil];
  196. statusBar = [self.webView convertRect:statusBar fromView:nil];
  197. screen = [self.webView convertRect:screen fromView:nil];
  198.  
  199. // if the webview is below the status bar, offset and shrink its frame
  200. if ([self settingForKey:@"StatusBarOverlaysWebView"] != nil && ![[self settingForKey:@"StatusBarOverlaysWebView"] boolValue]) {
  201. CGRect full, remainder;
  202. CGRectDivide(screen, &remainder, &full, statusBar.size.height, CGRectMinYEdge);
  203. screen = full;
  204. }
  205.  
  206. // Get the intersection of the keyboard and screen and move the webview above it
  207. // Note: we check for _shrinkView at this point instead of the beginning of the method to handle
  208. // the case where the user disabled shrinkView while the keyboard is showing.
  209. // The webview should always be able to return to full size
  210. CGRect keyboardIntersection = CGRectIntersection(screen, keyboard);
  211. if (CGRectContainsRect(screen, keyboardIntersection) && !CGRectIsEmpty(keyboardIntersection) && _shrinkView && self.keyboardIsVisible) {
  212. screen.size.height -= keyboardIntersection.size.height;
  213. self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView;
  214. }
  215.  
  216. // A view's frame is in its superview's coordinate system so we need to convert again
  217. self.webView.frame = [self.webView.superview convertRect:screen fromView:self.webView];
  218. }
  219.  
  220.  
  221.  
  222. #pragma mark UIScrollViewDelegate
  223.  
  224. - (void)scrollViewDidScroll:(UIScrollView*)scrollView
  225. {
  226. if (_shrinkView && _keyboardIsVisible) {
  227. CGFloat maxY = scrollView.contentSize.height - scrollView.bounds.size.height;
  228. if (scrollView.bounds.origin.y > maxY) {
  229. scrollView.bounds = CGRectMake(scrollView.bounds.origin.x, maxY,
  230. scrollView.bounds.size.width, scrollView.bounds.size.height);
  231. }
  232. }
  233. }
  234.  
  235. #pragma mark Plugin interface
  236.  
  237. - (void)shrinkView:(CDVInvokedUrlCommand*)command
  238. {
  239. if (command.arguments.count > 0) {
  240. id value = [command.arguments objectAtIndex:0];
  241. if (!([value isKindOfClass:[NSNumber class]])) {
  242. value = [NSNumber numberWithBool:NO];
  243. }
  244.  
  245. self.shrinkView = [value boolValue];
  246. }
  247.  
  248. [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.shrinkView]
  249. callbackId:command.callbackId];
  250. }
  251.  
  252. - (void)disableScrollingInShrinkView:(CDVInvokedUrlCommand*)command
  253. {
  254. if (command.arguments.count > 0) {
  255. id value = [command.arguments objectAtIndex:0];
  256. if (!([value isKindOfClass:[NSNumber class]])) {
  257. value = [NSNumber numberWithBool:NO];
  258. }
  259.  
  260. self.disableScrollingInShrinkView = [value boolValue];
  261. }
  262.  
  263. [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.disableScrollingInShrinkView]
  264. callbackId:command.callbackId];
  265. }
  266.  
  267. - (void)hideFormAccessoryBar:(CDVInvokedUrlCommand*)command
  268. {
  269. if (command.arguments.count > 0) {
  270. id value = [command.arguments objectAtIndex:0];
  271. if (!([value isKindOfClass:[NSNumber class]])) {
  272. value = [NSNumber numberWithBool:NO];
  273. }
  274.  
  275. self.hideFormAccessoryBar = [value boolValue];
  276. }
  277.  
  278. [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.hideFormAccessoryBar]
  279. callbackId:command.callbackId];
  280. }
  281.  
  282. - (void)hide:(CDVInvokedUrlCommand*)command
  283. {
  284. [self.webView endEditing:YES];
  285. }
  286.  
  287. #pragma mark dealloc
  288.  
  289. - (void)dealloc
  290. {
  291. // since this is ARC, remove observers only
  292. NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
  293.  
  294. [nc removeObserver:_keyboardShowObserver];
  295. [nc removeObserver:_keyboardHideObserver];
  296. [nc removeObserver:_keyboardWillShowObserver];
  297. [nc removeObserver:_keyboardWillHideObserver];
  298. [nc removeObserver:_shrinkViewKeyboardWillChangeFrameObserver];
  299. }
  300.  
  301. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement