I'm making a custom input method for the iPad, I want to be able to replace the system keyboard with my input method and enter text via that input method.
According to the documentation all I need to do is to set the inputView property with my view and it will be used instead of the system keyboard. I did that and it works, as far as showing the keyboard but how do I actually enter text into the text view?
Supposedly the text view needs to adopt the UIKeyInput and I can use the protocol's methods to enter the text but in reality UITextView doesn't adopt this protocol. conformsToProtocol:#protocol(UIKeyInput) returns NO and "deleteBackwards" is not implemented (insertText and hasText are implemented. In addition to that, "insertText" doesn't cause the textViewDidChange: delegate method to be invoked. Obviously I need to send the UIKeyInput method to some other object (a field editor?) but how do I get it?
Any ideas?
Assuming your keyboard has some buttons, why cant you just set a selector for your keys, and append to the textViews text when each button is clicked, I have done this an it works fine...Here is the method that actually does the "writing" to the UITextView, this method is part of a custom protocol defined by the inputView and is called on the delegate whenever a button is pressed, hope it helps, note: i submit ret when the return key is pushed and <- when backspace is pushed.
-(void)userDidInputString:(NSString*)s
{
NSRange r=padView.textView.selectedRange;
if([s isEqualToString:#"ret"])
s=#"\n";
if([s isEqualToString:#"<-"])
{
NSString *text=padView.textView.text;
if(r.location>0)
{
r.location=r.location-1;
r.length+=1;
}
[padView.textView setScrollEnabled:YES];
padView.textView.text=[text stringByReplacingCharactersInRange:r withString:#""];
[padView.textView setScrollEnabled:NO];
r.length=0;
[padView.textView setSelectedRange:r];
[note setNoteText:padView.textView.text];
}
else {
NSString *text=padView.textView.text;
[padView.textView setScrollEnabled:YES];
padView.textView.text=[text stringByReplacingCharactersInRange:r withString:s];
[padView.textView setScrollEnabled:NO];
r.location=r.location+[s length];
//whenever you modify the text by setting the UITextViews text property it resets the cursor to the end of the text view, we have this line below to go back to where the user left off
[padView.textView setSelectedRange:r];
}
}
Related
I'm using UIWebView to display formatted content. However, I need to replace the default keyboard for UITextViews/UITextFields with our own.
I can use grotesque methods to hide the default keyboard when it appears, but I can't find the text field to direct input to. UITextFieldTextDidBeginEditingNotification or UITextViewTextDidBeginEditingNotification is never fired off. I do see UIKeyboardWillShowNotification etc properly emitted.
It is important that the final result be App Store approved.
EDIT:
When the keyboard notification comes, note which HTML element is focused. Then make your view controller first responder.
[self becomeFirstResponder];
Your view controller should become first responder and return your custom input view.
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (UIView*)inputView {
return _customInputView;
}
When your custom input view gets input, you can pass it to the HTML element.
NSString* script = [NSString stringWithFormat:#"element.value += '%#';", input];
[_webView stringByEvaluatingJavascriptFromString:script];
In my iPad app there are 3 textboxes where i am using popoverview controller on second text box.
here their are 2 cases
In First Case:
As i finish editing the first textbox and click the next button on keyboard that time the keyboard is resigning perfectly and the popoverview controller is opened on second text box.Here i had written the code when the next button of the first textbox click at that time the second textbox should became FirstResponder.
In Second Case:
Here the actual problem,
When i finish editing the first textbox and directly touches the second textbox without clicking the next button on keyboard, that time popoverview controller menu is opened on second textbox and the keyboard is unable to resign , the keyboard is strucking over their my code for resigning the keyboard is not working.
Write your code which you used on NEXT button event of Keyboard in this bellow method...
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if (textField == yourFirstTextBox) {
// write your code here
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField *)textfield
{
if ([textfield tag]==yourtextfieldtag)//set tag for your textfield
{
[yourfirsttextfield resignFirstResponder];
[yoursecondtextfield resignFirstResponder];
.
.
.
//Write all textField with resignFirstResponder
}
}
Here is the way you can handle your SoftKeypad
Handling Soft Keypad in iPhone Tutorial
There are three simple ways to handle keypad here
Keypad go back when Button clicked.
Keypad go back when user click on Return or Done button on keypad.
Keypad go back when user Touch on Background screen/view.
Just follow 3rd way in you case.
What you need to do is just crate a method in which call
method for the desired text field.
and Updated Related UIView class to UIControl in Interface Builder.
as I have written all the information step by step to make it more easy and clear.
Here is the responsible code snip
- (IBAction)keypadGoBack:(id)sender {
[userNameTextField resignFirstResponder];
[passwordTextField resignFirstResponder];
}
Hope this will help you.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField==yourTextField)
{
[self.view endEditing:YES];
// Write Your Popoverview Code / Extra Code
return NO;
}
return YES;
}
Here this method will get called when you will hit textfield.
And check the textfield with yourtextFieldName if its match..it will resign all keyboard.if there is more than one also..with the help of.
[self.view endEditing:YES];
And you can do Extra Code also For popoverview and return no means It will not give keyboard to that perticuler textField.
Thanks.
I have 2 textFields side by side, countryCodeTextField and cellphoneTextField
On countryCodeTextField. I have an action selectCountry that happens on Edit Did Begin on the countryCodeTextField
- (IBAction)selectCountry:(id)sender {
countryCodeTextField.delegate = self;
[countryCodeTextField resignFirstResponder];
Note that self implements the <UITextFieldDelegate>.
Problem is when user click's cellphone the keyboard is displayed if he clicks on countryCodeTextField the keyboard is never dismissed.
If the person clicks the countryCode first then the keyboard never appears(which is what I want).
Why isn't the keyboard hidden when the user clicks cellphoneTextField first and then countryCodeTextField?
If you don't want the user to be able to edit a particular UITextField, set it to not be enabled.
UITextField *textField = ... // Allocated somehow
textfield.enabled = NO
Or just check the enabled checkbox in Interface Builder. Then the textfield will still be there and you'll be able to update it by configuring the text. But as sort of mentioned in comments, users expect UITextFields to be editable.
Also, why are you setting the delegate in the IBAction callback? I would think you'd be better off doing this in Interface Builder or when you create the UITextField in code.
EDIT:
Ok - so you want users to be able to select the box, but then bring up a custom subview(s) from which they select something which will fill the box.
So set the UITextField delegate when you create it (as mentioned above) and implement the following from the UITextFieldDelegate protocol:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO;
}
to return NO. Note that if you are using the same delegate for both of your UITextFields, you will need to make this method return YES for the other field. For example, something like:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == countryTextField)
return NO;
return YES;
}
Hopefully this should stop the keyboard being displayed - and now you have to work out how to fire your own subviews, which I'd suggest doing via an IBAction (touch up or something perhaps). You'll have to test various things out here, but remember you're kinda corrupting the point of UITextField and maybe it'll work and maybe it won't, and maybe it'll break in the next iOS upgrade.
Okay, so first, I think you shouldn't be using a UITextField. I think you should be using a UIButton and have the current value showing as the button's title. However, if you have your heart set on it, I would use our good friend inputView, a property on UITextField, and set that to your custom input view (which I assume is a UIPickerView or similar.)
This has the added bonus of not breaking your app horribly for blind and visually impaired users, something you should probably be aware of before you go messing about with standard behaviour.
In your method :
- (IBAction)textFieldDidBeginEditing: (UITextField *)textField
call this :
[textField becomeFirstResponder];
and apply checks for the two fields i.e., when textField is the countryCodeTextField write :
[textField resignFirstResponder];
and call your method :
[self selectCountry];
In this method display the list of country codes.
So Your code will be :
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return YES;
}
- (IBAction)textFieldDidBeginEditing: (UITextField *)textField{
[textField becomeFirstResponder];
if (textField == countryCodeTextField){
[textField resignFirstResponder];
[self selectCountry];
}
}
-(IBAction)selectCountry{
//display the list no need to do anything with the textfield.Only set text of TextField as the selected countrycode.
}
My application is looking like the below snap in some scenario.
There is one UITextField to get the department name from the user. Initially the "Done" button in navigation bar is set to disabled. That is, set right bar button's enabled property to NO
The UIKeyBoard of the text field was made by the below code
fieldForDepartment.keyboardAppearance = UIKeyboardAppearanceAlert; //This provides the black appearance to the keyboard
fieldForDepartment.returnKeyType = UIReturnKeyDone; //This set the return key type as Done
fieldForDepartment.clearButtonMode = UITextFieldViewModeWhileEditing; //This is used because i want a small cross button in the right end of my text field to clear the text field value
(Here fieldForDepartment is the UITextField instance's name)
I want to enable the "Done" button in the navigation bar if & only if, there should be atleast one letter in the text field (even may be a space). The "Done" button should get disable if there is a no letter in my text field.
For that, I implemented this code...
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([[fieldForDepartment.text stringByReplacingCharactersInRange:range withString:string] isEqual:#""] || [fieldForDepartment.text stringByReplacingCharactersInRange:range withString:string] == nil) {
rightBarButton.enabled = NO;
}
else {
rightBarButton.enabled = YES;
}
return YES;
}
This method textField: shouldChangeCharactersInRange: get called for each letter press in the keyboard.
[fieldForDepartment.text stringByReplacingCharactersInRange:range withString:string] will bring the current string(included the last letter pressed) from the UITextField
So when pressing a letter in the text field the application will be like this...
Here my problem comes..
The "Done" button in the UIKeyboard is always highlighted. So this violates the behavior of the "Done" button in the navigation bar. I want to disable/enable the UIKeyboard's Done button in the same way the navigation bar's Done button works. Is it possible?
Some of the questions in my mind are..
Can i disable the "Done" button of UIKeyboard?
or
Can i just change the background color & selection color of the Done button in UIKeyboard? (So that the user may feel that the button can not be pressed)
or
Can i hide the Done button in UIKeyboard?
Please suggest which one is the good way to solve my problem...
Thanks in Advance
There is an Auto-enable Return Key setting in the Text trait's section of the Interface builder properties. It does exactly what you need, just make sure to check it.
If you need to do the change in the code, use enablesReturnKeyAutomatically property of the UITextField (this is actually defined in the UITextInputTraits protocol that the class implements)
I have a custom keyboard I want to show when the user taps a UITextField. But at the same time I want to show the cursor in the textfield. If if return a NO for canBecomeFirstResponder, it doesn't show the default keyboard but doesn't show the cursor either.
Can someone please help me out?
Thanks.
The answer to your problem is to create a view for your custom keyboard and then edit the inputView property of your UITextField and pass it the view for your custom keyboard.
I hope that helps.
override following two methods in UITextFieldDelegate. Note that this approach is valid for both UITextField and UITextView (in which case you override corresponding methods in UITextViewDelegate)
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (!textField.inputView) {
//hides the keyboard, but still shows the cursor to allow user to view entire text, even if it exceeds the bounds of the textfield
textField.inputView = [[UIView alloc] initWithFrame:CGRectZero];
}
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
return NO;
}
Seems like what you want is a UITextField with a custom keyboard. Create the class CustomKeyboard : UIView and add buttons/layout the view. Then for your textfield just set the inputView property to an instance of the class CustomKeyboard textField.inputView = customKeyboard;. You'll need to set the inputView property to be readwrite as well #property (readwrite, retain) UIView *inputView; By setting the inputView property, the standard iPhone keyboards will not appear when the textfield becomes first responder.
Register as keyboard notification observer (e.g. in the view controller where you want to hide the keyboard):-
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(hideKeyboard:) name:UIKeyboardWillShowNotification object:nil];
Put in the hideKeyboard: function:-
-(void)hideKeyboard:(NSNotification *)notification {
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
for (UIView *keyboard in [keyboardWindow subviews]) {
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES) {
keyboard.alpha = 0;
}
}
}
}
(Thanks to luvieere in this post for showing me how to get the keyboard)
I'm not sure of the point, but why not just use a UILabel with the same contents of the text field and decorated to look like your text field with a cursor in it. Swap it out for a UITextField when you want input.
There are 2 solutions to your problem.
1) Setting the alpha of the keyboard to 0 will make the keyboard invisible... which may be all you want. The cursor will appear.
2) UITextField implements the UITextInputTraits Protocol. It will always call the keyboard when it becomes the first responder. You will need to inherit from either it or anther class to change that default behavior.
Good luck.
If you tell us what your trying to accomplish we might be about to suggest a more elegant way of accomplishing it.
Have fun.
I see two solutions - either create custom animation (and stop or start it depending on the first responder status of the text field), or play with inputView property.
Here is a solution for inputView approach:
Set inputView property of the UITextField to empty view and ask it to become first responder. This will effectively hide default inputView (i.e. keyboard), but will continue showing blinking cursor.
Add Tap gesture recognizer, and when user taps UITextField, set the inputView property to your custom keyboard, dismiss the keyboard and ask the UITextField to become first responder again.
class BlinkingTextFieldVC: UIViewController {
var blinkingTextField: UITextField!
override func onViewDidLoad() {
setupView()
}
func setupView() {
blinkingTextField = UITextField()
blinkingTextField.inputView = UIView() // empty view will be shown as input method
blinkingTextField.becomeFirstResponder()
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(blinkingTextFieldTapped(_:)))
blinkingTextField.addGestureRecognizer(tapGuesture)
}
func blinkingTextFieldTapped(_ gesture: UITapGestureRecognizer) {
if gesture.state == .ended {
view.endEditing(true)
blinkingTextField.inputView = nil // set your custom input view or nil for default keyboard
blinkingTextField.becomeFirstResponder()
}
}
}
Why do you even need the cursor ?
I think all you need to do, is when ever a user press a key on your own keyboard, you can update the text value of the input.