fzhangtj
6 年前
当前提交
b52ad1df
共有 14 个文件被更改,包括 1448 次插入 和 0 次删除
-
8Runtime/Plugins/platform.meta
-
8Runtime/Plugins/platform/ios.meta
-
6Runtime/Plugins/platform/ios/UIWidgetsMessageManager.h
-
109Runtime/Plugins/platform/ios/UIWidgetsMessageManager.h.meta
-
39Runtime/Plugins/platform/ios/UIWidgetsMessageManager.mm
-
104Runtime/Plugins/platform/ios/UIWidgetsMessageManager.mm.meta
-
32Runtime/Plugins/platform/ios/UIWidgetsTextInputDelegate.h
-
109Runtime/Plugins/platform/ios/UIWidgetsTextInputDelegate.h.meta
-
32Runtime/Plugins/platform/ios/UIWidgetsTextInputPlugin.h
-
109Runtime/Plugins/platform/ios/UIWidgetsTextInputPlugin.h.meta
-
788Runtime/Plugins/platform/ios/UIWidgetsTextInputPlugin.mm
-
104Runtime/Plugins/platform/ios/UIWidgetsTextInputPlugin.mm.meta
|
|||
fileFormatVersion: 2 |
|||
guid: e93b613e0d2074e979e1920d32dabdd7 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d8264d285bf7842f99ef80594606a5ba |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSMESSAGEMANAGER_H_ |
|||
#define PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSMESSAGEMANAGER_H_ |
|||
|
|||
void UIWidgetsMethodMessage(NSString* channel, NSString* method, NSArray *args); |
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 0705d6959bdbd4e8880b5d9ac52d8bba |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
'': Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Android: 0 |
|||
Exclude Editor: 0 |
|||
Exclude Linux: 0 |
|||
Exclude Linux64: 0 |
|||
Exclude LinuxUniversal: 0 |
|||
Exclude OSXUniversal: 0 |
|||
Exclude WebGL: 0 |
|||
Exclude Win: 0 |
|||
Exclude Win64: 0 |
|||
Exclude iOS: 0 |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: ARMv7 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
Facebook: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Facebook: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Linux |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86 |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86_64 |
|||
- first: |
|||
Standalone: LinuxUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
WebGL: WebGL |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
iPhone: iOS |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
AddToEmbeddedBinaries: false |
|||
CompileFlags: -fno-objc-arc |
|||
FrameworkDependencies: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#include "UIWidgetsMessageManager.h" |
|||
|
|||
#define MAX_OBJECT_NAME_LENGTH 256 |
|||
static char uiwidgetsMessageObjectName[MAX_OBJECT_NAME_LENGTH] = {0}; |
|||
|
|||
|
|||
static char* MakeStringCopy (const char* string) |
|||
{ |
|||
if (string == NULL) |
|||
return NULL; |
|||
|
|||
char* res = (char*)malloc(strlen(string) + 1); |
|||
strcpy(res, string); |
|||
return res; |
|||
} |
|||
|
|||
void UIWidgetsMethodMessage(NSString* channel, NSString* method, NSArray *args) |
|||
{ |
|||
const char* msg = NULL; |
|||
NSError *error; |
|||
NSDictionary* dict = @{ |
|||
@"channel": channel, |
|||
@"method": method, |
|||
@"args": args |
|||
}; |
|||
|
|||
NSData* data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error]; |
|||
NSString* text = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; |
|||
msg = [text UTF8String]; |
|||
|
|||
UnitySendMessage(uiwidgetsMessageObjectName, "OnUIWidgetsMethodMessage", msg); |
|||
} |
|||
|
|||
|
|||
extern "C" { |
|||
void UIWidgetsMessageSetObjectName(const char* name) { |
|||
strlcpy(uiwidgetsMessageObjectName, name, MAX_OBJECT_NAME_LENGTH); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4238c84dc02f445fcb9e8d755dc9c441 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
'': Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Android: 1 |
|||
Exclude Editor: 1 |
|||
Exclude Linux: 1 |
|||
Exclude Linux64: 1 |
|||
Exclude LinuxUniversal: 1 |
|||
Exclude OSXUniversal: 1 |
|||
Exclude WebGL: 1 |
|||
Exclude Win: 1 |
|||
Exclude Win64: 1 |
|||
Exclude iOS: 0 |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: ARMv7 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
Facebook: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Facebook: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Linux |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: x86 |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: x86_64 |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
iPhone: iOS |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
AddToEmbeddedBinaries: false |
|||
CompileFlags: -fno-objc-arc |
|||
FrameworkDependencies: |
|||
- first: |
|||
tvOS: tvOS |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTDELEGATE_H_ |
|||
#define PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTDELEGATE_H_ |
|||
#import <Foundation/Foundation.h> |
|||
|
|||
typedef NS_ENUM(NSInteger, UIWidgetsTextInputAction) { |
|||
UIWidgetsTextInputActionUnspecified, |
|||
UIWidgetsTextInputActionDone, |
|||
UIWidgetsTextInputActionGo, |
|||
UIWidgetsTextInputActionSend, |
|||
UIWidgetsTextInputActionSearch, |
|||
UIWidgetsTextInputActionNext, |
|||
UIWidgetsTextInputActionContinue, |
|||
UIWidgetsTextInputActionJoin, |
|||
UIWidgetsTextInputActionRoute, |
|||
UIWidgetsTextInputActionEmergencyCall, |
|||
UIWidgetsTextInputActionNewline, |
|||
}; |
|||
|
|||
@protocol UIWidgetsTextInputDelegate <NSObject> |
|||
|
|||
- (void)updateEditingClient:(int)client withState:(NSDictionary*)state; |
|||
- (void)performAction:(UIWidgetsTextInputAction)action withClient:(int)client; |
|||
|
|||
@end |
|||
|
|||
|
|||
@interface DefaultUIWidgetsTextInputDelegate : NSObject <UIWidgetsTextInputDelegate> |
|||
- (void)updateEditingClient:(int)client withState:(NSDictionary*)state; |
|||
- (void)performAction:(UIWidgetsTextInputAction)action withClient:(int)client; |
|||
@end |
|||
|
|||
#endif // PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTDELEGATE_H_ |
|
|||
fileFormatVersion: 2 |
|||
guid: 2ea9fef069ce54398a5a9b8ff7b61a1e |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
'': Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Android: 0 |
|||
Exclude Editor: 0 |
|||
Exclude Linux: 0 |
|||
Exclude Linux64: 0 |
|||
Exclude LinuxUniversal: 0 |
|||
Exclude OSXUniversal: 0 |
|||
Exclude WebGL: 0 |
|||
Exclude Win: 0 |
|||
Exclude Win64: 0 |
|||
Exclude iOS: 0 |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: ARMv7 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
Facebook: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Facebook: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Linux |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86 |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86_64 |
|||
- first: |
|||
Standalone: LinuxUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
WebGL: WebGL |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
iPhone: iOS |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
AddToEmbeddedBinaries: false |
|||
CompileFlags: -fno-objc-arc |
|||
FrameworkDependencies: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTPLUGIN_H_ |
|||
#define PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTPLUGIN_H_ |
|||
|
|||
#import <UIKit/UIKit.h> |
|||
#include "UIWidgetsTextInputDelegate.h" |
|||
|
|||
@interface UIWidgetsTextInputPlugin : NSObject |
|||
|
|||
@property(nonatomic, assign) id<UIWidgetsTextInputDelegate> textInputDelegate; |
|||
|
|||
- (UIView<UITextInput>*)textInputView; |
|||
|
|||
@end |
|||
|
|||
@interface UIWidgetsTextPosition : UITextPosition |
|||
|
|||
@property(nonatomic, readonly) NSUInteger index; |
|||
|
|||
+ (instancetype)positionWithIndex:(NSUInteger)index; |
|||
- (instancetype)initWithIndex:(NSUInteger)index; |
|||
|
|||
@end |
|||
|
|||
@interface UIWidgetsTextRange : UITextRange <NSCopying> |
|||
|
|||
@property(nonatomic, readonly) NSRange range; |
|||
|
|||
+ (instancetype)rangeWithNSRange:(NSRange)range; |
|||
|
|||
@end |
|||
|
|||
#endif // PLATFORM_IOS_FRAMEWORK_SOURCE_UIWIDGETSTEXTINPUTPLUGIN_H_ |
|
|||
fileFormatVersion: 2 |
|||
guid: e051adc12d2a04dffa17a9ee58501006 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
'': Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Android: 0 |
|||
Exclude Editor: 0 |
|||
Exclude Linux: 0 |
|||
Exclude Linux64: 0 |
|||
Exclude LinuxUniversal: 0 |
|||
Exclude OSXUniversal: 0 |
|||
Exclude WebGL: 0 |
|||
Exclude Win: 0 |
|||
Exclude Win64: 0 |
|||
Exclude iOS: 0 |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: ARMv7 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
Facebook: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Facebook: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Linux |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86 |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: x86_64 |
|||
- first: |
|||
Standalone: LinuxUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
WebGL: WebGL |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
iPhone: iOS |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
AddToEmbeddedBinaries: false |
|||
CompileFlags: -fno-objc-arc |
|||
FrameworkDependencies: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#include "UIWidgetsTextInputPlugin.h" |
|||
#include "UIWidgetsMessageManager.h" |
|||
#include <Foundation/Foundation.h> |
|||
#include <UIKit/UIKit.h> |
|||
|
|||
static const char _kTextAffinityDownstream[] = "TextAffinity.downstream"; |
|||
static const char _kTextAffinityUpstream[] = "TextAffinity.upstream"; |
|||
|
|||
static UIKeyboardType ToUIKeyboardType(NSDictionary* type) { |
|||
NSString* inputType = type[@"name"]; |
|||
if ([inputType isEqualToString:@"TextInputType.text"]) |
|||
return UIKeyboardTypeDefault; |
|||
if ([inputType isEqualToString:@"TextInputType.multiline"]) |
|||
return UIKeyboardTypeDefault; |
|||
if ([inputType isEqualToString:@"TextInputType.number"]) { |
|||
if ([type[@"signed"] boolValue]) |
|||
return UIKeyboardTypeNumbersAndPunctuation; |
|||
return UIKeyboardTypeDecimalPad; |
|||
} |
|||
if ([inputType isEqualToString:@"TextInputType.phone"]) |
|||
return UIKeyboardTypePhonePad; |
|||
if ([inputType isEqualToString:@"TextInputType.emailAddress"]) |
|||
return UIKeyboardTypeEmailAddress; |
|||
if ([inputType isEqualToString:@"TextInputType.url"]) |
|||
return UIKeyboardTypeURL; |
|||
return UIKeyboardTypeDefault; |
|||
} |
|||
|
|||
static UITextAutocapitalizationType ToUITextAutoCapitalizationType(NSDictionary* type) { |
|||
NSString* textCapitalization = type[@"textCapitalization"]; |
|||
if ([textCapitalization isEqualToString:@"TextCapitalization.characters"]) { |
|||
return UITextAutocapitalizationTypeAllCharacters; |
|||
} else if ([textCapitalization isEqualToString:@"TextCapitalization.sentences"]) { |
|||
return UITextAutocapitalizationTypeSentences; |
|||
} else if ([textCapitalization isEqualToString:@"TextCapitalization.words"]) { |
|||
return UITextAutocapitalizationTypeWords; |
|||
} |
|||
return UITextAutocapitalizationTypeNone; |
|||
} |
|||
|
|||
static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) { |
|||
// Where did the term "unspecified" come from? iOS has a "default" and Android |
|||
// has "unspecified." These 2 terms seem to mean the same thing but we need |
|||
// to pick just one. "unspecified" was chosen because "default" is often a |
|||
// reserved word in languages with switch statements (dart, java, etc). |
|||
if ([inputType isEqualToString:@"TextInputAction.unspecified"]) |
|||
return UIReturnKeyDefault; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.done"]) |
|||
return UIReturnKeyDone; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.go"]) |
|||
return UIReturnKeyGo; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.send"]) |
|||
return UIReturnKeySend; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.search"]) |
|||
return UIReturnKeySearch; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.next"]) |
|||
return UIReturnKeyNext; |
|||
|
|||
if (@available(iOS 9.0, *)) |
|||
if ([inputType isEqualToString:@"TextInputAction.continueAction"]) |
|||
return UIReturnKeyContinue; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.join"]) |
|||
return UIReturnKeyJoin; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.route"]) |
|||
return UIReturnKeyRoute; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.emergencyCall"]) |
|||
return UIReturnKeyEmergencyCall; |
|||
|
|||
if ([inputType isEqualToString:@"TextInputAction.newline"]) |
|||
return UIReturnKeyDefault; |
|||
|
|||
// Present default key if bad input type is given. |
|||
return UIReturnKeyDefault; |
|||
} |
|||
|
|||
#pragma mark - UIWidgetsTextPosition |
|||
|
|||
@implementation UIWidgetsTextPosition |
|||
|
|||
+ (instancetype)positionWithIndex:(NSUInteger)index { |
|||
return [[[UIWidgetsTextPosition alloc] initWithIndex:index] autorelease]; |
|||
} |
|||
|
|||
- (instancetype)initWithIndex:(NSUInteger)index { |
|||
self = [super init]; |
|||
if (self) { |
|||
_index = index; |
|||
} |
|||
return self; |
|||
} |
|||
|
|||
@end |
|||
|
|||
#pragma mark - UIWidgetsTextRange |
|||
|
|||
@implementation UIWidgetsTextRange |
|||
|
|||
+ (instancetype)rangeWithNSRange:(NSRange)range { |
|||
return [[[UIWidgetsTextRange alloc] initWithNSRange:range] autorelease]; |
|||
} |
|||
|
|||
- (instancetype)initWithNSRange:(NSRange)range { |
|||
self = [super init]; |
|||
if (self) { |
|||
_range = range; |
|||
} |
|||
return self; |
|||
} |
|||
|
|||
- (UITextPosition*)start { |
|||
return [UIWidgetsTextPosition positionWithIndex:self.range.location]; |
|||
} |
|||
|
|||
- (UITextPosition*)end { |
|||
return [UIWidgetsTextPosition positionWithIndex:self.range.location + self.range.length]; |
|||
} |
|||
|
|||
- (BOOL)isEmpty { |
|||
return self.range.length == 0; |
|||
} |
|||
|
|||
- (id)copyWithZone:(NSZone*)zone { |
|||
return [[UIWidgetsTextRange allocWithZone:zone] initWithNSRange:self.range]; |
|||
} |
|||
|
|||
@end |
|||
|
|||
@interface UIWidgetsTextInputView : UIView <UITextInput> |
|||
|
|||
// UITextInput |
|||
@property(nonatomic, readonly) NSMutableString* text; |
|||
@property(nonatomic, readonly) NSMutableString* markedText; |
|||
@property(readwrite, copy) UITextRange* selectedTextRange; |
|||
@property(nonatomic, strong) UITextRange* markedTextRange; |
|||
@property(nonatomic, copy) NSDictionary* markedTextStyle; |
|||
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate; |
|||
|
|||
// UITextInputTraits |
|||
@property(nonatomic) UITextAutocapitalizationType autocapitalizationType; |
|||
@property(nonatomic) UITextAutocorrectionType autocorrectionType; |
|||
@property(nonatomic) UITextSpellCheckingType spellCheckingType; |
|||
@property(nonatomic) BOOL enablesReturnKeyAutomatically; |
|||
@property(nonatomic) UIKeyboardAppearance keyboardAppearance; |
|||
@property(nonatomic) UIKeyboardType keyboardType; |
|||
@property(nonatomic) UIReturnKeyType returnKeyType; |
|||
@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; |
|||
|
|||
@property(nonatomic, assign) id<UIWidgetsTextInputDelegate> textInputDelegate; |
|||
|
|||
@end |
|||
|
|||
@implementation UIWidgetsTextInputView { |
|||
int _textInputClient; |
|||
const char* _selectionAffinity; |
|||
UIWidgetsTextRange* _selectedTextRange; |
|||
} |
|||
|
|||
@synthesize tokenizer = _tokenizer; |
|||
|
|||
- (instancetype)init { |
|||
self = [super init]; |
|||
|
|||
if (self) { |
|||
_textInputClient = 0; |
|||
_selectionAffinity = _kTextAffinityUpstream; |
|||
|
|||
// UITextInput |
|||
_text = [[NSMutableString alloc] init]; |
|||
_markedText = [[NSMutableString alloc] init]; |
|||
_selectedTextRange = [[UIWidgetsTextRange alloc] initWithNSRange:NSMakeRange(0, 0)]; |
|||
|
|||
// UITextInputTraits |
|||
_autocapitalizationType = UITextAutocapitalizationTypeSentences; |
|||
_autocorrectionType = UITextAutocorrectionTypeDefault; |
|||
_spellCheckingType = UITextSpellCheckingTypeDefault; |
|||
_enablesReturnKeyAutomatically = NO; |
|||
_keyboardAppearance = UIKeyboardAppearanceDefault; |
|||
_keyboardType = UIKeyboardTypeDefault; |
|||
_returnKeyType = UIReturnKeyDone; |
|||
_secureTextEntry = NO; |
|||
} |
|||
|
|||
return self; |
|||
} |
|||
|
|||
- (void)dealloc { |
|||
[_text release]; |
|||
[_markedText release]; |
|||
[_markedTextRange release]; |
|||
[_selectedTextRange release]; |
|||
[_tokenizer release]; |
|||
[super dealloc]; |
|||
} |
|||
|
|||
- (void)setTextInputClient:(int)client { |
|||
_textInputClient = client; |
|||
} |
|||
|
|||
- (void)setTextInputState:(NSDictionary*)state { |
|||
NSString* newText = state[@"text"]; |
|||
BOOL textChanged = ![self.text isEqualToString:newText]; |
|||
if (textChanged) { |
|||
[self.inputDelegate textWillChange:self]; |
|||
[self.text setString:newText]; |
|||
} |
|||
|
|||
NSInteger selectionBase = [state[@"selectionBase"] intValue]; |
|||
NSInteger selectionExtent = [state[@"selectionExtent"] intValue]; |
|||
NSRange selectedRange = [self clampSelection:NSMakeRange(MIN(selectionBase, selectionExtent), |
|||
ABS(selectionBase - selectionExtent)) |
|||
forText:self.text]; |
|||
NSRange oldSelectedRange = [(UIWidgetsTextRange*)self.selectedTextRange range]; |
|||
if (selectedRange.location != oldSelectedRange.location || |
|||
selectedRange.length != oldSelectedRange.length) { |
|||
[self.inputDelegate selectionWillChange:self]; |
|||
[self setSelectedTextRange:[UIWidgetsTextRange rangeWithNSRange:selectedRange] |
|||
updateEditingState:NO]; |
|||
_selectionAffinity = _kTextAffinityDownstream; |
|||
if ([state[@"selectionAffinity"] isEqualToString:@(_kTextAffinityUpstream)]) |
|||
_selectionAffinity = _kTextAffinityUpstream; |
|||
[self.inputDelegate selectionDidChange:self]; |
|||
} |
|||
|
|||
NSInteger composingBase = [state[@"composingBase"] intValue]; |
|||
NSInteger composingExtent = [state[@"composingExtent"] intValue]; |
|||
NSRange composingRange = [self clampSelection:NSMakeRange(MIN(composingBase, composingExtent), |
|||
ABS(composingBase - composingExtent)) |
|||
forText:self.text]; |
|||
self.markedTextRange = |
|||
composingRange.length > 0 ? [UIWidgetsTextRange rangeWithNSRange:composingRange] : nil; |
|||
|
|||
if (textChanged) { |
|||
[self.inputDelegate textDidChange:self]; |
|||
|
|||
// For consistency with Android behavior, send an update to the framework. |
|||
[self updateEditingState]; |
|||
} |
|||
} |
|||
|
|||
- (NSRange)clampSelection:(NSRange)range forText:(NSString*)text { |
|||
int start = MIN(MAX(range.location, 0), text.length); |
|||
int length = MIN(range.length, text.length - start); |
|||
return NSMakeRange(start, length); |
|||
} |
|||
|
|||
#pragma mark - UIResponder Overrides |
|||
|
|||
- (BOOL)canBecomeFirstResponder { |
|||
return YES; |
|||
} |
|||
|
|||
#pragma mark - UITextInput Overrides |
|||
|
|||
- (id<UITextInputTokenizer>)tokenizer { |
|||
if (_tokenizer == nil) { |
|||
_tokenizer = [[UITextInputStringTokenizer alloc] initWithTextInput:self]; |
|||
} |
|||
return _tokenizer; |
|||
} |
|||
|
|||
- (UITextRange*)selectedTextRange { |
|||
return [[_selectedTextRange copy] autorelease]; |
|||
} |
|||
|
|||
- (void)setSelectedTextRange:(UITextRange*)selectedTextRange { |
|||
[self setSelectedTextRange:selectedTextRange updateEditingState:YES]; |
|||
} |
|||
|
|||
- (void)setSelectedTextRange:(UITextRange*)selectedTextRange updateEditingState:(BOOL)update { |
|||
if (_selectedTextRange != selectedTextRange) { |
|||
UITextRange* oldSelectedRange = _selectedTextRange; |
|||
_selectedTextRange = [selectedTextRange copy]; |
|||
[oldSelectedRange release]; |
|||
|
|||
if (update) |
|||
[self updateEditingState]; |
|||
} |
|||
} |
|||
|
|||
- (id)insertDictationResultPlaceholder { |
|||
return @""; |
|||
} |
|||
|
|||
- (void)removeDictationResultPlaceholder:(id)placeholder willInsertResult:(BOOL)willInsertResult { |
|||
} |
|||
|
|||
- (NSString*)textInRange:(UITextRange*)range { |
|||
NSRange textRange = ((UIWidgetsTextRange*)range).range; |
|||
return [self.text substringWithRange:textRange]; |
|||
} |
|||
|
|||
- (void)replaceRange:(UITextRange*)range withText:(NSString*)text { |
|||
NSRange replaceRange = ((UIWidgetsTextRange*)range).range; |
|||
NSRange selectedRange = _selectedTextRange.range; |
|||
// Adjust the text selection: |
|||
// * reduce the length by the intersection length |
|||
// * adjust the location by newLength - oldLength + intersectionLength |
|||
NSRange intersectionRange = NSIntersectionRange(replaceRange, selectedRange); |
|||
if (replaceRange.location <= selectedRange.location) |
|||
selectedRange.location += text.length - replaceRange.length; |
|||
if (intersectionRange.location != NSNotFound) { |
|||
selectedRange.location += intersectionRange.length; |
|||
selectedRange.length -= intersectionRange.length; |
|||
} |
|||
|
|||
[self.text replaceCharactersInRange:[self clampSelection:replaceRange forText:self.text] |
|||
withString:text]; |
|||
[self setSelectedTextRange:[UIWidgetsTextRange rangeWithNSRange:[self clampSelection:selectedRange |
|||
forText:self.text]] |
|||
updateEditingState:NO]; |
|||
|
|||
[self updateEditingState]; |
|||
} |
|||
|
|||
- (BOOL)shouldChangeTextInRange:(UITextRange*)range replacementText:(NSString*)text { |
|||
if (self.returnKeyType == UIReturnKeyDefault && [text isEqualToString:@"\n"]) { |
|||
[_textInputDelegate performAction:UIWidgetsTextInputActionNewline withClient:_textInputClient]; |
|||
return YES; |
|||
} |
|||
|
|||
if ([text isEqualToString:@"\n"]) { |
|||
UIWidgetsTextInputAction action; |
|||
switch (self.returnKeyType) { |
|||
case UIReturnKeyDefault: |
|||
action = UIWidgetsTextInputActionUnspecified; |
|||
break; |
|||
case UIReturnKeyDone: |
|||
action = UIWidgetsTextInputActionDone; |
|||
break; |
|||
case UIReturnKeyGo: |
|||
action = UIWidgetsTextInputActionGo; |
|||
break; |
|||
case UIReturnKeySend: |
|||
action = UIWidgetsTextInputActionSend; |
|||
break; |
|||
case UIReturnKeySearch: |
|||
case UIReturnKeyGoogle: |
|||
case UIReturnKeyYahoo: |
|||
action = UIWidgetsTextInputActionSearch; |
|||
break; |
|||
case UIReturnKeyNext: |
|||
action = UIWidgetsTextInputActionNext; |
|||
break; |
|||
case UIReturnKeyContinue: |
|||
action = UIWidgetsTextInputActionContinue; |
|||
break; |
|||
case UIReturnKeyJoin: |
|||
action = UIWidgetsTextInputActionJoin; |
|||
break; |
|||
case UIReturnKeyRoute: |
|||
action = UIWidgetsTextInputActionRoute; |
|||
break; |
|||
case UIReturnKeyEmergencyCall: |
|||
action = UIWidgetsTextInputActionEmergencyCall; |
|||
break; |
|||
} |
|||
|
|||
[_textInputDelegate performAction:action withClient:_textInputClient]; |
|||
return NO; |
|||
} |
|||
|
|||
return YES; |
|||
} |
|||
|
|||
- (void)setMarkedText:(NSString*)markedText selectedRange:(NSRange)markedSelectedRange { |
|||
NSRange selectedRange = _selectedTextRange.range; |
|||
NSRange markedTextRange = ((UIWidgetsTextRange*)self.markedTextRange).range; |
|||
|
|||
if (markedText == nil) |
|||
markedText = @""; |
|||
|
|||
if (markedTextRange.length > 0) { |
|||
// Replace text in the marked range with the new text. |
|||
[self replaceRange:self.markedTextRange withText:markedText]; |
|||
markedTextRange.length = markedText.length; |
|||
} else { |
|||
// Replace text in the selected range with the new text. |
|||
[self replaceRange:_selectedTextRange withText:markedText]; |
|||
markedTextRange = NSMakeRange(selectedRange.location, markedText.length); |
|||
} |
|||
|
|||
self.markedTextRange = |
|||
markedTextRange.length > 0 ? [UIWidgetsTextRange rangeWithNSRange:markedTextRange] : nil; |
|||
|
|||
NSUInteger selectionLocation = markedSelectedRange.location + markedTextRange.location; |
|||
selectedRange = NSMakeRange(selectionLocation, markedSelectedRange.length); |
|||
[self setSelectedTextRange:[UIWidgetsTextRange rangeWithNSRange:[self clampSelection:selectedRange |
|||
forText:self.text]] |
|||
updateEditingState:YES]; |
|||
} |
|||
|
|||
- (void)unmarkText { |
|||
self.markedTextRange = nil; |
|||
[self updateEditingState]; |
|||
} |
|||
|
|||
- (UITextRange*)textRangeFromPosition:(UITextPosition*)fromPosition |
|||
toPosition:(UITextPosition*)toPosition { |
|||
NSUInteger fromIndex = ((UIWidgetsTextPosition*)fromPosition).index; |
|||
NSUInteger toIndex = ((UIWidgetsTextPosition*)toPosition).index; |
|||
return [UIWidgetsTextRange rangeWithNSRange:NSMakeRange(fromIndex, toIndex - fromIndex)]; |
|||
} |
|||
|
|||
/** Returns the range of the character sequence at the specified index in the |
|||
* text. */ |
|||
- (NSRange)rangeForCharacterAtIndex:(NSUInteger)index { |
|||
if (index < self.text.length) |
|||
return [self.text rangeOfComposedCharacterSequenceAtIndex:index]; |
|||
return NSMakeRange(index, 0); |
|||
} |
|||
|
|||
- (NSUInteger)decrementOffsetPosition:(NSUInteger)position { |
|||
return [self rangeForCharacterAtIndex:MAX(0, position - 1)].location; |
|||
} |
|||
|
|||
- (NSUInteger)incrementOffsetPosition:(NSUInteger)position { |
|||
NSRange charRange = [self rangeForCharacterAtIndex:position]; |
|||
return MIN(position + charRange.length, self.text.length); |
|||
} |
|||
|
|||
- (UITextPosition*)positionFromPosition:(UITextPosition*)position offset:(NSInteger)offset { |
|||
NSUInteger offsetPosition = ((UIWidgetsTextPosition*)position).index; |
|||
if (offset >= 0) { |
|||
for (NSInteger i = 0; i < offset && offsetPosition < self.text.length; ++i) |
|||
offsetPosition = [self incrementOffsetPosition:offsetPosition]; |
|||
} else { |
|||
for (NSInteger i = 0; i < ABS(offset) && offsetPosition > 0; ++i) |
|||
offsetPosition = [self decrementOffsetPosition:offsetPosition]; |
|||
} |
|||
return [UIWidgetsTextPosition positionWithIndex:offsetPosition]; |
|||
} |
|||
|
|||
- (UITextPosition*)positionFromPosition:(UITextPosition*)position |
|||
inDirection:(UITextLayoutDirection)direction |
|||
offset:(NSInteger)offset { |
|||
// TODO(cbracken) Add RTL handling. |
|||
switch (direction) { |
|||
case UITextLayoutDirectionLeft: |
|||
case UITextLayoutDirectionUp: |
|||
return [self positionFromPosition:position offset:offset * -1]; |
|||
case UITextLayoutDirectionRight: |
|||
case UITextLayoutDirectionDown: |
|||
return [self positionFromPosition:position offset:1]; |
|||
} |
|||
} |
|||
|
|||
- (UITextPosition*)beginningOfDocument { |
|||
return [UIWidgetsTextPosition positionWithIndex:0]; |
|||
} |
|||
|
|||
- (UITextPosition*)endOfDocument { |
|||
return [UIWidgetsTextPosition positionWithIndex:self.text.length]; |
|||
} |
|||
|
|||
- (NSComparisonResult)comparePosition:(UITextPosition*)position toPosition:(UITextPosition*)other { |
|||
NSUInteger positionIndex = ((UIWidgetsTextPosition*)position).index; |
|||
NSUInteger otherIndex = ((UIWidgetsTextPosition*)other).index; |
|||
if (positionIndex < otherIndex) |
|||
return NSOrderedAscending; |
|||
if (positionIndex > otherIndex) |
|||
return NSOrderedDescending; |
|||
return NSOrderedSame; |
|||
} |
|||
|
|||
- (NSInteger)offsetFromPosition:(UITextPosition*)from toPosition:(UITextPosition*)toPosition { |
|||
return ((UIWidgetsTextPosition*)toPosition).index - ((UIWidgetsTextPosition*)from).index; |
|||
} |
|||
|
|||
- (UITextPosition*)positionWithinRange:(UITextRange*)range |
|||
farthestInDirection:(UITextLayoutDirection)direction { |
|||
NSUInteger index; |
|||
switch (direction) { |
|||
case UITextLayoutDirectionLeft: |
|||
case UITextLayoutDirectionUp: |
|||
index = ((UIWidgetsTextPosition*)range.start).index; |
|||
break; |
|||
case UITextLayoutDirectionRight: |
|||
case UITextLayoutDirectionDown: |
|||
index = ((UIWidgetsTextPosition*)range.end).index; |
|||
break; |
|||
} |
|||
return [UIWidgetsTextPosition positionWithIndex:index]; |
|||
} |
|||
|
|||
- (UITextRange*)characterRangeByExtendingPosition:(UITextPosition*)position |
|||
inDirection:(UITextLayoutDirection)direction { |
|||
NSUInteger positionIndex = ((UIWidgetsTextPosition*)position).index; |
|||
NSUInteger startIndex; |
|||
NSUInteger endIndex; |
|||
switch (direction) { |
|||
case UITextLayoutDirectionLeft: |
|||
case UITextLayoutDirectionUp: |
|||
startIndex = [self decrementOffsetPosition:positionIndex]; |
|||
endIndex = positionIndex; |
|||
break; |
|||
case UITextLayoutDirectionRight: |
|||
case UITextLayoutDirectionDown: |
|||
startIndex = positionIndex; |
|||
endIndex = [self incrementOffsetPosition:positionIndex]; |
|||
break; |
|||
} |
|||
return [UIWidgetsTextRange rangeWithNSRange:NSMakeRange(startIndex, endIndex - startIndex)]; |
|||
} |
|||
|
|||
#pragma mark - UITextInput text direction handling |
|||
|
|||
- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition*)position |
|||
inDirection:(UITextStorageDirection)direction { |
|||
return UITextWritingDirectionNatural; |
|||
} |
|||
|
|||
- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection |
|||
forRange:(UITextRange*)range { |
|||
} |
|||
|
|||
#pragma mark - UITextInput cursor, selection rect handling |
|||
|
|||
- (CGRect)firstRectForRange:(UITextRange*)range { |
|||
return CGRectZero; |
|||
} |
|||
|
|||
- (CGRect)caretRectForPosition:(UITextPosition*)position { |
|||
return CGRectZero; |
|||
} |
|||
|
|||
- (UITextPosition*)closestPositionToPoint:(CGPoint)point { |
|||
NSUInteger currentIndex = ((UIWidgetsTextPosition*)_selectedTextRange.start).index; |
|||
return [UIWidgetsTextPosition positionWithIndex:currentIndex]; |
|||
} |
|||
|
|||
- (NSArray*)selectionRectsForRange:(UITextRange*)range { |
|||
return @[]; |
|||
} |
|||
|
|||
- (UITextPosition*)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange*)range { |
|||
return range.start; |
|||
} |
|||
|
|||
- (UITextRange*)characterRangeAtPoint:(CGPoint)point { |
|||
NSUInteger currentIndex = ((UIWidgetsTextPosition*)_selectedTextRange.start).index; |
|||
return [UIWidgetsTextRange rangeWithNSRange:[self rangeForCharacterAtIndex:currentIndex]]; |
|||
} |
|||
|
|||
#pragma mark - UIKeyInput Overrides |
|||
|
|||
- (void)updateEditingState { |
|||
NSUInteger selectionBase = ((UIWidgetsTextPosition*)_selectedTextRange.start).index; |
|||
NSUInteger selectionExtent = ((UIWidgetsTextPosition*)_selectedTextRange.end).index; |
|||
|
|||
NSUInteger composingBase = 0; |
|||
NSUInteger composingExtent = 0; |
|||
if (self.markedTextRange != nil) { |
|||
composingBase = ((UIWidgetsTextPosition*)self.markedTextRange.start).index; |
|||
composingExtent = ((UIWidgetsTextPosition*)self.markedTextRange.end).index; |
|||
} |
|||
[_textInputDelegate updateEditingClient:_textInputClient |
|||
withState:@{ |
|||
@"selectionBase" : @(selectionBase), |
|||
@"selectionExtent" : @(selectionExtent), |
|||
@"selectionAffinity" : @(_selectionAffinity), |
|||
@"selectionIsDirectional" : @(false), |
|||
@"composingBase" : @(composingBase), |
|||
@"composingExtent" : @(composingExtent), |
|||
@"text" : [NSString stringWithString:self.text], |
|||
}]; |
|||
} |
|||
|
|||
- (BOOL)hasText { |
|||
return self.text.length > 0; |
|||
} |
|||
|
|||
- (void)insertText:(NSString*)text { |
|||
_selectionAffinity = _kTextAffinityDownstream; |
|||
[self replaceRange:_selectedTextRange withText:text]; |
|||
} |
|||
|
|||
- (void)deleteBackward { |
|||
_selectionAffinity = _kTextAffinityDownstream; |
|||
if (!_selectedTextRange.isEmpty) |
|||
[self replaceRange:_selectedTextRange withText:@""]; |
|||
} |
|||
|
|||
@end |
|||
|
|||
/** |
|||
* Hides `UIWidgetsTextInputView` from iOS accessibility system so it |
|||
* does not show up twice, once where it is in the `UIView` hierarchy, |
|||
* and a second time as part of the `SemanticsObject` hierarchy. |
|||
*/ |
|||
@interface UIWidgetsTextInputViewAccessibilityHider : UIView { |
|||
} |
|||
|
|||
@end |
|||
|
|||
@implementation UIWidgetsTextInputViewAccessibilityHider { |
|||
} |
|||
|
|||
- (BOOL)accessibilityElementsHidden { |
|||
return YES; |
|||
} |
|||
|
|||
@end |
|||
|
|||
@implementation UIWidgetsTextInputPlugin { |
|||
UIWidgetsTextInputView* _view; |
|||
UIWidgetsTextInputViewAccessibilityHider* _inputHider; |
|||
} |
|||
|
|||
@synthesize textInputDelegate = _textInputDelegate; |
|||
|
|||
- (instancetype)init { |
|||
self = [super init]; |
|||
|
|||
if (self) { |
|||
_view = [[UIWidgetsTextInputView alloc] init]; |
|||
_inputHider = [[UIWidgetsTextInputViewAccessibilityHider alloc] init]; |
|||
} |
|||
|
|||
return self; |
|||
} |
|||
|
|||
- (void)dealloc { |
|||
[self hideTextInput]; |
|||
[_view release]; |
|||
[_inputHider release]; |
|||
|
|||
[super dealloc]; |
|||
} |
|||
|
|||
- (UIView<UITextInput>*)textInputView { |
|||
return _view; |
|||
} |
|||
|
|||
- (void)showTextInput { |
|||
NSAssert([UIApplication sharedApplication].keyWindow != nullptr, |
|||
@"The application must have a key window since the keyboard client " |
|||
@"must be part of the responder chain to function"); |
|||
_view.textInputDelegate = _textInputDelegate; |
|||
[_inputHider addSubview:_view]; |
|||
[[UIApplication sharedApplication].keyWindow addSubview:_inputHider]; |
|||
[_view becomeFirstResponder]; |
|||
} |
|||
|
|||
- (void)hideTextInput { |
|||
[_view resignFirstResponder]; |
|||
[_view removeFromSuperview]; |
|||
[_inputHider removeFromSuperview]; |
|||
} |
|||
|
|||
- (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configuration { |
|||
NSDictionary* inputType = configuration[@"inputType"]; |
|||
NSString* keyboardAppearance = configuration[@"keyboardAppearance"]; |
|||
_view.keyboardType = ToUIKeyboardType(inputType); |
|||
_view.returnKeyType = ToUIReturnKeyType(configuration[@"inputAction"]); |
|||
_view.autocapitalizationType = ToUITextAutoCapitalizationType(configuration); |
|||
if ([keyboardAppearance isEqualToString:@"Brightness.dark"]) { |
|||
_view.keyboardAppearance = UIKeyboardAppearanceDark; |
|||
} else if ([keyboardAppearance isEqualToString:@"Brightness.light"]) { |
|||
_view.keyboardAppearance = UIKeyboardAppearanceLight; |
|||
} else { |
|||
_view.keyboardAppearance = UIKeyboardAppearanceDefault; |
|||
} |
|||
_view.secureTextEntry = [configuration[@"obscureText"] boolValue]; |
|||
NSString* autocorrect = configuration[@"autocorrect"]; |
|||
_view.autocorrectionType = autocorrect && ![autocorrect boolValue] |
|||
? UITextAutocorrectionTypeNo |
|||
: UITextAutocorrectionTypeDefault; |
|||
[_view setTextInputClient:client]; |
|||
[_view reloadInputViews]; |
|||
} |
|||
|
|||
- (void)setTextInputEditingState:(NSDictionary*)state { |
|||
[_view setTextInputState:state]; |
|||
} |
|||
|
|||
- (void)clearTextInputClient { |
|||
[_view setTextInputClient:0]; |
|||
} |
|||
|
|||
+ (instancetype)sharedInstance { |
|||
static UIWidgetsTextInputPlugin *sharedInstance = nil; |
|||
static dispatch_once_t onceToken; |
|||
|
|||
dispatch_once(&onceToken, ^{ |
|||
sharedInstance = [[UIWidgetsTextInputPlugin alloc] init]; |
|||
sharedInstance.textInputDelegate = [[DefaultUIWidgetsTextInputDelegate alloc] init]; |
|||
}); |
|||
return sharedInstance; |
|||
} |
|||
@end |
|||
|
|||
|
|||
@implementation DefaultUIWidgetsTextInputDelegate |
|||
|
|||
- (void)updateEditingClient:(int)client withState:(NSDictionary*)state { |
|||
UIWidgetsMethodMessage(@"TextInput", @"TextInputClient.updateEditingState", @[@(client), state]); |
|||
} |
|||
|
|||
- (void)performAction:(UIWidgetsTextInputAction)action withClient:(int)client { |
|||
NSString* actionString; |
|||
switch (action) { |
|||
case UIWidgetsTextInputActionUnspecified: |
|||
// Where did the term "unspecified" come from? iOS has a "default" and Android |
|||
// has "unspecified." These 2 terms seem to mean the same thing but we need |
|||
// to pick just one. "unspecified" was chosen because "default" is often a |
|||
// reserved word in languages with switch statements (dart, java, etc). |
|||
actionString = @"TextInputAction.unspecified"; |
|||
break; |
|||
case UIWidgetsTextInputActionDone: |
|||
actionString = @"TextInputAction.done"; |
|||
break; |
|||
case UIWidgetsTextInputActionGo: |
|||
actionString = @"TextInputAction.go"; |
|||
break; |
|||
case UIWidgetsTextInputActionSend: |
|||
actionString = @"TextInputAction.send"; |
|||
break; |
|||
case UIWidgetsTextInputActionSearch: |
|||
actionString = @"TextInputAction.search"; |
|||
break; |
|||
case UIWidgetsTextInputActionNext: |
|||
actionString = @"TextInputAction.next"; |
|||
break; |
|||
case UIWidgetsTextInputActionContinue: |
|||
actionString = @"TextInputAction.continue"; |
|||
break; |
|||
case UIWidgetsTextInputActionJoin: |
|||
actionString = @"TextInputAction.join"; |
|||
break; |
|||
case UIWidgetsTextInputActionRoute: |
|||
actionString = @"TextInputAction.route"; |
|||
break; |
|||
case UIWidgetsTextInputActionEmergencyCall: |
|||
actionString = @"TextInputAction.emergencyCall"; |
|||
break; |
|||
case UIWidgetsTextInputActionNewline: |
|||
actionString = @"TextInputAction.newline"; |
|||
break; |
|||
} |
|||
|
|||
UIWidgetsMethodMessage(@"TextInput", @"TextInputClient.performAction", @[@(client), actionString]); |
|||
} |
|||
@end |
|||
|
|||
extern "C" { |
|||
|
|||
void UIWidgetsTextInputShow() { |
|||
[[UIWidgetsTextInputPlugin sharedInstance] showTextInput]; |
|||
} |
|||
|
|||
void UIWidgetsTextInputHide() { |
|||
[[UIWidgetsTextInputPlugin sharedInstance] hideTextInput]; |
|||
} |
|||
|
|||
void UIWidgetsTextInputSetClient(int client, const char* configurationJson) { |
|||
NSError *jsonError = nil; |
|||
NSString *nsJsonString=[NSString stringWithUTF8String:configurationJson]; |
|||
NSData *objectData = [nsJsonString dataUsingEncoding:NSUTF8StringEncoding]; |
|||
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData |
|||
options:NSJSONReadingMutableContainers |
|||
error:&jsonError]; |
|||
|
|||
[[UIWidgetsTextInputPlugin sharedInstance] setTextInputClient:client withConfiguration:json]; |
|||
} |
|||
|
|||
void UIWidgetsTextInputSetTextInputEditingState(const char* jsonText) { |
|||
NSError *jsonError; |
|||
NSString *nsJsonString=[NSString stringWithUTF8String:jsonText]; |
|||
NSData *objectData = [nsJsonString dataUsingEncoding:NSUTF8StringEncoding]; |
|||
NSDictionary *args = [NSJSONSerialization JSONObjectWithData:objectData |
|||
options:NSJSONReadingMutableContainers |
|||
error:&jsonError]; |
|||
[[UIWidgetsTextInputPlugin sharedInstance] setTextInputEditingState:args]; |
|||
} |
|||
|
|||
void UIWidgetsTextInputClearTextInputClient() { |
|||
[[UIWidgetsTextInputPlugin sharedInstance] clearTextInputClient]; |
|||
} |
|||
} |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 4bb403cfcbd364d8b830518ed5a17166 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
'': Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Android: 1 |
|||
Exclude Editor: 1 |
|||
Exclude Linux: 1 |
|||
Exclude Linux64: 1 |
|||
Exclude LinuxUniversal: 1 |
|||
Exclude OSXUniversal: 1 |
|||
Exclude WebGL: 1 |
|||
Exclude Win: 1 |
|||
Exclude Win64: 1 |
|||
Exclude iOS: 0 |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: ARMv7 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
Facebook: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Facebook: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Linux |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: x86 |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: x86_64 |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
iPhone: iOS |
|||
second: |
|||
enabled: 1 |
|||
settings: |
|||
AddToEmbeddedBinaries: false |
|||
CompileFlags: -fno-objc-arc |
|||
FrameworkDependencies: |
|||
- first: |
|||
tvOS: tvOS |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue