unity中使用九宫格输入中文的问题

android的没问题

iOS的一直输入不了中文

解决办法:原文地址http://my.oschina.net/araya/blog/680943

#include "Keyboard.h"
#include "DisplayManager.h"
#include "UnityForwardDecls.h"
#include <string>

// Respect values passed from prefix header or CFlags
#ifndef FILTER_EMOJIS_IOS_KEYBOARD
// Set this flag to 0 in order to allow emoji symbols to be entered in the iOS keyboard.
#define FILTER_EMOJIS_IOS_KEYBOARD 1
#endif

static KeyboardDelegate*	_keyboard = nil;

static bool					_shouldHideInput = false;
static bool					_shouldHideInputChanged = false;
static const unsigned       kToolBarHeight = 64;

@implementation KeyboardDelegate
{
	// UI handling
	// in case of single line we use UITextField inside UIToolbar
	// in case of multi-line input we use UITextView with UIToolbar as accessory view
	// toolbar buttons are kept around to prevent releasing them
	// tvOS does not support multiline input thus only UITextField option is implemented
#if UNITY_IOS
	UITextView*		textView;

	UIToolbar*		viewToolbar;
	NSArray*		viewToolbarItems;
#endif

	UITextField*	textField;

	// keep toolbar items for both single- and multi- line edit in NSArray to make sure they are kept around
#if UNITY_IOS
	UIToolbar*		fieldToolbar;
	NSArray*		fieldToolbarItems;
#endif

	// inputView is view used for actual input (it will be responder): UITextField [single-line] or UITextView [multi-line]
	// editView is the "root" view for keyboard: UIToolbar [single-line] or UITextView [multi-line]
	UIView*			inputView;
	UIView*			editView;


	CGRect			_area;
	NSString*		initialText;

	UIKeyboardType	keyboardType;

	BOOL			_multiline;
	BOOL			_inputHidden;
	BOOL			_active;
	BOOL			_done;
	BOOL			_canceled;

	BOOL			_rotating;
}

@synthesize area;
@synthesize active		= _active;
@synthesize done		= _done;
@synthesize canceled	= _canceled;
@synthesize text;

// While emoji symbols are still shown in the iOS keyboard, they are all filtered by the
// shouldChangeCharactersInRange method below.
#if FILTER_EMOJIS_IOS_KEYBOARD

bool stringContainsEmoji(NSString *string)
{
	__block BOOL returnValue = NO;
	[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
		options:NSStringEnumerationByComposedCharacterSequences
		usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop)
		{
			const unichar hs = [substring characterAtIndex:0];

			// Surrogate pair
			if(hs >= 0xD800 && hs <= 0xDBFF)
			{
				if(substring.length > 1)
				{
					// Compute the code point in the U+10000 - U+10FFFF plane.
					const unichar ls = [substring characterAtIndex:1];
					const int uc = ((hs - 0xD800) * 0x400) + (ls - 0xDC00) + 0x10000;

					// The ranges for the various emoji tables are as follows.
					// Musical -> [U+1D000, U+1D24F]
					// Miscellaneous Symbols and Pictographs -> [U+1F300, U+1F5FF]
					// Emoticons -> [U+1F600, U+1F64F]
					// Transport and Map Symbols -> [U+1F680, U+1F6FF]
					// Supplemental Symbols and Pictographs -> [U+1F900, U+1F9FF]
					if(uc >= 0x1D000 && uc <= 0x1F9FF)
					{
						returnValue = YES;
					}
				}
			}
			else if(substring.length > 1)
			{
				const unichar ls = [substring characterAtIndex:1];

				if(ls == 0x20E3)
				{
					// Filter all the emojis for numbers.
					returnValue = YES;
				}
				else if(hs >= 0x270A && hs <= 0x270D)
				{
					// Filter all the various hand symbols (e.g., victory sign, writing hand, etc).
					returnValue = YES;
				}
			}
			else
			{
				// Non surrogate pair.
				if(hs >= 0x2100 && hs <= 0x27FF)
				{
					// Filter the following emoji ranges.
					// Letterlike Symbols -> [U+2100, U+214F]
					// Number Forms -> [U+2150, U+218F]
					// Arrows -> [U+2190, U+21FF]
					// Dingbats -> [U+2700, U+27BF]
					// Supplemental Arrows-A -> [U+27F0–U+27FF]
					returnValue = YES;
				}
				else if(hs >= 0x2900 && hs <= 0x297F)
				{
					// Filter Supplemental Arrows-B -> [U+2900, U+297F]
					returnValue = YES;
				}
				else if(hs >= 0x2B05 && hs <= 0x2BFF)
				{
					// Filter Miscellaneous Symbols and Arrows -> [U+2B00, U+2BFF]
					returnValue = YES;
				}
			}
		}];

	return returnValue;
}

// See the documentation for this method in http://apple.co/1OMnz8D.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
	// Process the input string using the 'stringContainsEmoji' function and return NO or YES
	// depending on whether it needs to be added to the UITexField or skipped altogether, respectively.
	// We need to do this because Unity's UI doesn't provide proper Unicode support yet.
	return !stringContainsEmoji(string);
}

#endif // FILTER_EMOJIS_IOS_KEYBOARD

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]){
        //判断输入的字是否是回车,即按下return
        //在这里做你响应return键的代码
        [self hide];
        return NO; //这里返回NO,就代表return键值失效,即页面上按下return,不会出现换行,如果为yes,则输入页面会换行
    }
    return YES;
}

- (BOOL)textViewShouldReturn:(UITextView*)textFieldObj
{
    [self hide];
    return YES;
}

- (BOOL)textFieldShouldReturn:(UITextField*)textFieldObj
{
	[self hide];
	return YES;
}
- (void)textInputDone:(id)sender
{
	[self hide];
}
- (void)textInputCancel:(id)sender
{
	_canceled = true;
	[self hide];
}

- (BOOL)textViewShouldBeginEditing:(UITextView*)view
{
#if !UNITY_TVOS
	view.inputAccessoryView = viewToolbar;
#endif
	return YES;
}

#if UNITY_IOS
- (void)keyboardDidShow:(NSNotification*)notification;
{
	if (notification.userInfo == nil || inputView == nil)
		return;

	CGRect srcRect	= [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
	CGRect rect		= [UnityGetGLView() convertRect:srcRect fromView:nil];

	[self positionInput:rect x:rect.origin.x y:rect.origin.y];
	_active = YES;
}

- (void)keyboardWillHide:(NSNotification*)notification;
{
	[self systemHideKeyboard];
}
- (void)keyboardDidChangeFrame:(NSNotification*)notification;
{
	_active = true;

	CGRect srcRect	= [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
	CGRect rect		= [UnityGetGLView() convertRect:srcRect fromView: nil];

	if(rect.origin.y >= [UnityGetGLView() bounds].size.height)
		[self systemHideKeyboard];
	else
		[self positionInput:rect x:rect.origin.x y:rect.origin.y];
}
#endif

+ (void)Initialize
{
	NSAssert(_keyboard == nil, @"[KeyboardDelegate Initialize] called after creating keyboard");
	if(!_keyboard)
		_keyboard = [[KeyboardDelegate alloc] init];
}

+ (KeyboardDelegate*)Instance
{
	if(!_keyboard)
		_keyboard = [[KeyboardDelegate alloc] init];

	return _keyboard;
}

#if UNITY_IOS
struct CreateToolbarResult
{
	UIToolbar*	toolbar;
	NSArray*	items;
};
- (CreateToolbarResult)createToolbarWithView:(UIView*)view
{
	UIToolbar* toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,160,320, kToolBarHeight)];
	UnitySetViewTouchProcessing(toolbar, touchesIgnored);
	toolbar.hidden = NO;

	UIBarButtonItem* inputItem	= view ? [[UIBarButtonItem alloc] initWithCustomView:view] : nil;
	UIBarButtonItem* doneItem	= [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(textInputDone:)];
	UIBarButtonItem* cancelItem	= [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(textInputCancel:)];

	NSArray* items = view ? @[inputItem, doneItem, cancelItem] : @[doneItem, cancelItem];
	toolbar.items = items;

	inputItem = nil;
	doneItem = nil;
	cancelItem = nil;

	CreateToolbarResult ret = {toolbar, items};
	return ret;
}
#endif

- (id)init
{
	NSAssert(_keyboard == nil, @"You can have only one instance of KeyboardDelegate");
	self = [super init];
	if(self)
	{
#if UNITY_IOS
		textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 480, 480, 30)];
		textView.delegate = self;
		textView.font = [UIFont systemFontOfSize:18.0];
		textView.hidden = YES;
        textView.returnKeyType = UIReturnKeyDone;

#endif

		textField = [[UITextField alloc] initWithFrame:CGRectMake(0,0,120,30)];
		textField.delegate = self;
		textField.borderStyle = UITextBorderStyleRoundedRect;
		textField.font = [UIFont systemFontOfSize:20.0];
		textField.clearButtonMode = UITextFieldViewModeWhileEditing;

		#define CREATE_TOOLBAR(t, i, v)									\
		do {															\
			CreateToolbarResult res = [self createToolbarWithView:v];	\
			t = res.toolbar;											\
			i = res.items;												\
		} while(0)

#if UNITY_IOS
		//CREATE_TOOLBAR(viewToolbar, viewToolbarItems, nil);
		CREATE_TOOLBAR(fieldToolbar, fieldToolbarItems, textField);
#endif

		#undef CREATE_TOOLBAR

#if UNITY_IOS
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
#endif

		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textInputDone:) name:UITextFieldTextDidEndEditingNotification object:nil];
	}

	return self;
}

- (void) setTextInputTraits: (id<UITextInputTraits>) traits
				  withParam: (KeyboardShowParam) param
					withCap: (UITextAutocapitalizationType) capitalization
{
	traits.keyboardType	= param.keyboardType;
	traits.autocorrectionType = param.autocorrectionType;
	traits.secureTextEntry = param.secure;
	traits.keyboardAppearance = param.appearance;
	traits.autocapitalizationType = capitalization;
}


- (void)setKeyboardParams:(KeyboardShowParam)param
{
	if(_active)
		[self hide];

	initialText = param.text ? [[NSString alloc] initWithUTF8String: param.text] : @"";

	UITextAutocapitalizationType capitalization = UITextAutocapitalizationTypeSentences;
	if(param.keyboardType == UIKeyboardTypeURL || param.keyboardType == UIKeyboardTypeEmailAddress)
		capitalization = UITextAutocapitalizationTypeNone;

#if UNITY_IOS
//	_multiline = param.multiline;
    _multiline = true;

	if (_multiline)
	{
		textView.text = initialText;
		[self setTextInputTraits:textView withParam:param withCap:capitalization];
	}
	else
	{
		textField.text = initialText;
		[self setTextInputTraits:textField withParam:param withCap:capitalization];
		textField.placeholder = [NSString stringWithUTF8String:param.placeholder];
	}
	inputView = _multiline ? textView : textField;
	editView = _multiline ? textView : fieldToolbar;

#else // UNITY_TVOS
	textField.text = initialText;
	[self setTextInputTraits:textField withParam:param withCap:capitalization];
	textField.placeholder = [NSString stringWithUTF8String:param.placeholder];
	inputView = textField;
	editView = textField;
#endif

    [self shouldHideInput:_shouldHideInput];

	_done		= NO;
	_canceled	= NO;
	_active		= YES;
}

// we need to show/hide keyboard to react to orientation too, so extract we extract UI fiddling

- (void)showUI
{
	// if we unhide everything now the input will be shown smaller then needed quickly (and resized later)
	// so unhide only when keyboard is actually shown (we will update it when reacting to ios notifications)
	editView.hidden = YES;

	[UnityGetGLView() addSubview:editView];
	[inputView becomeFirstResponder];
}
- (void)hideUI
{
	[inputView resignFirstResponder];

	[editView removeFromSuperview];
	editView.hidden = YES;
}
- (void)systemHideKeyboard
{
	_active = editView.isFirstResponder;
	editView.hidden = YES;

	_area = CGRectMake(0,0,0,0);
}

- (void)show
{
	[self showUI];
}
- (void)hide
{
	[self hideUI];
	_done = YES;
}

- (void)updateInputHidden
{
	if(_shouldHideInputChanged)
	{
		[self shouldHideInput:_shouldHideInput];
		_shouldHideInputChanged = false;
	}

	textField.returnKeyType = _inputHidden ? UIReturnKeyDone : UIReturnKeyDefault;

	editView.hidden		= _inputHidden ? YES : NO;
	inputView.hidden	= _inputHidden ? YES : NO;
}

#if UNITY_IOS
- (void)positionInput:(CGRect)kbRect x:(float)x y:(float)y
{
	if(_multiline)
	{
		// use smaller area for iphones and bigger one for ipads
		//int height = UnityDeviceDPI() > 300 ? 75 : 100;

		//editView.frame	= CGRectMake(0, y - kToolBarHeight, kbRect.size.width, height);
        int height = UnityDeviceDPI() > 300 ? 38 : 100;
        editView.frame	= CGRectMake(0, y - height, kbRect.size.width, height);
	}
	else
	{
		CGRect   statusFrame	= [UIApplication sharedApplication].statusBarFrame;
		unsigned statusHeight	= statusFrame.size.height;

		editView.frame	= CGRectMake(0, y - kToolBarHeight - statusHeight, kbRect.size.width, kToolBarHeight);
        inputView.frame	= CGRectMake(inputView.frame.origin.x,
                                     inputView.frame.origin.y,
                                     kbRect.size.width - 3*18 - 2*50,
                                     inputView.frame.size.height);
	}

	_area = CGRectMake(x, y, kbRect.size.width, kbRect.size.height);
	[self updateInputHidden];
}
#endif

- (CGRect)queryArea
{
	return editView.hidden ? _area : CGRectUnion(_area, editView.frame);
}

+ (void)StartReorientation
{
	if(_keyboard && _keyboard.active)
	{
		[CATransaction begin];
		[_keyboard hideUI];
		[CATransaction commit];

		// not pretty but seems like easiest way to keep "we are rotating" status
		_keyboard->_rotating = YES;
	}
}

+ (void)FinishReorientation
{
	if(_keyboard && _keyboard->_rotating)
	{
		[CATransaction begin];
		[_keyboard showUI];
		[CATransaction commit];

		_keyboard->_rotating = NO;
	}
}

- (NSString*)getText
{
	if (_canceled)
		return initialText;
	else
	{
#if UNITY_TVOS
		return [textField text];
#else
		return _multiline ? [textView text] : [textField text];
#endif
	}
}

- (void) setTextWorkaround:(id<UITextInput>)textInput text:(NSString*)newText
{
	UITextPosition* begin = [textInput beginningOfDocument];
	UITextPosition* end = [textInput endOfDocument];
	UITextRange* allText = [textInput textRangeFromPosition:begin toPosition:end];
	[textInput setSelectedTextRange:allText];
	[textInput insertText:newText];
}

- (void)setText:(NSString*)newText
{
#if UNITY_IOS
	// We can't use setText on iOS7 because it does not update the undo stack.
	// We still prefer setText on other iOSes, because an undo operation results
	// in a smaller selection shown on the UI
	if(_ios70orNewer && !_ios80orNewer)
		[self setTextWorkaround: (_multiline ? textView : textField) text:newText];

	if(_multiline)
		textView.text = newText;
	else
		textField.text = newText;
#else
	textField.text = newText;
#endif
}

- (void)shouldHideInput:(BOOL)hide
{
	if(hide)
	{
		switch(keyboardType)
		{
			case UIKeyboardTypeDefault:                 hide = YES;	break;
			case UIKeyboardTypeASCIICapable:            hide = YES;	break;
			case UIKeyboardTypeNumbersAndPunctuation:   hide = YES;	break;
			case UIKeyboardTypeURL:                     hide = YES;	break;
			case UIKeyboardTypeNumberPad:               hide = NO;	break;
			case UIKeyboardTypePhonePad:                hide = NO;	break;
			case UIKeyboardTypeNamePhonePad:            hide = NO;	break;
			case UIKeyboardTypeEmailAddress:            hide = YES;	break;
			default:                                    hide = NO;	break;
		}
	}

	_inputHidden = hide;
}

@end



//==============================================================================
//
//  Unity Interface:

extern "C" void UnityKeyboard_Create(unsigned keyboardType, int autocorrection, int multiline, int secure, int alert, const char* text, const char* placeholder)
{
#if UNITY_TVOS
	// Not supported. The API for showing keyboard for editing multi-line text
	// is not available on tvOS
	multiline = false;
#endif

	static const UIKeyboardType keyboardTypes[] =
	{
		UIKeyboardTypeDefault,
		UIKeyboardTypeASCIICapable,
		UIKeyboardTypeNumbersAndPunctuation,
		UIKeyboardTypeURL,
		UIKeyboardTypeNumberPad,
		UIKeyboardTypePhonePad,
		UIKeyboardTypeNamePhonePad,
		UIKeyboardTypeEmailAddress,
	};

	static const UITextAutocorrectionType autocorrectionTypes[] =
	{
		UITextAutocorrectionTypeNo,
		UITextAutocorrectionTypeDefault,
	};

	static const UIKeyboardAppearance keyboardAppearances[] =
	{
		UIKeyboardAppearanceDefault,
		UIKeyboardAppearanceAlert,
	};

	KeyboardShowParam param =
	{
		text, placeholder,
		keyboardTypes[keyboardType],
		autocorrectionTypes[autocorrection],
		keyboardAppearances[alert],
		(BOOL)multiline, (BOOL)secure
	};

	[[KeyboardDelegate Instance] setKeyboardParams:param];
}

extern "C" void UnityKeyboard_Show()
{
	// do not send hide if didnt create keyboard
	// TODO: probably assert?
	if(!_keyboard)
		return;

	[[KeyboardDelegate Instance] show];
}
extern "C" void UnityKeyboard_Hide()
{
	// do not send hide if didnt create keyboard
	// TODO: probably assert?
	if(!_keyboard)
		return;

	[[KeyboardDelegate Instance] hide];
}

extern "C" void UnityKeyboard_SetText(const char* text)
{
	[KeyboardDelegate Instance].text = [NSString stringWithUTF8String: text];
}

extern "C" NSString* UnityKeyboard_GetText()
{
	return [KeyboardDelegate Instance].text;
}

extern "C" int UnityKeyboard_IsActive()
{
	return (_keyboard && _keyboard.active) ? 1 : 0;
}

extern "C" int UnityKeyboard_IsDone()
{
	return (_keyboard && _keyboard.done) ? 1 : 0;
}

extern "C" int UnityKeyboard_WasCanceled()
{
	return (_keyboard && _keyboard.canceled) ? 1 : 0;
}

extern "C" void UnityKeyboard_SetInputHidden(int hidden)
{
	_shouldHideInput		= hidden;
	_shouldHideInputChanged	= true;

	// update hidden status only if keyboard is on screen to avoid showing input view out of nowhere
	if(_keyboard && _keyboard.active)
		[_keyboard updateInputHidden];
}

extern "C" int UnityKeyboard_IsInputHidden()
{
	return _shouldHideInput ? 1 : 0;
}

extern "C" void UnityKeyboard_GetRect(float* x, float* y, float* w, float* h)
{
	CGRect area = _keyboard ? _keyboard.area : CGRectMake(0,0,0,0);

	// convert to unity coord system

	float	multX	= (float)GetMainDisplaySurface()->targetW / UnityGetGLView().bounds.size.width;
	float	multY	= (float)GetMainDisplaySurface()->targetH / UnityGetGLView().bounds.size.height;

	*x = 0;
	*y = area.origin.y * multY;
	*w = area.size.width * multX;
	*h = area.size.height * multY;
}
    原文作者:九宫格问题
    原文地址: https://blog.csdn.net/xieyanbill/article/details/52075680
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞