Does anyone have an idea if we get a delegate call back from the keyboard when ".?123" button is tapped on it? We have put a customized number pad on the text keypad and want to remove it once user taps on ".?123" button to avoid duplicate keys.
Any suggestions.
There isn't any notification that will give you what you want. In fact, there isn't any public API that gives you access to the keyboard at that level. The only way I can think of to do this, is to put a transparent button over top the .?123 key, and detect that, and then pass on the touch to the underlying button. The button views are buried very deeply in the view hierarchy. I used this code to first, find the keyboard, and then log the views (UIKBKeyViews) that include that button. The five views in the log below appear to be the uppercase,backspace,.?123,spacebar, and return views.
-(void) keyboardUp: (NSNotification*) notification { // called from UIKeyboardDidShowNotification
UIWindow *tempWindow = [[[UIApplication sharedApplication] windows]objectAtIndex:1];
UIView *keyboard;
for(int i = 0; i < [tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES) {
// NSLog(#"Keyboard subviews are: %#",keyboard.subviews);
NSLog(#"%#",[[[[[[[[[[[[[UIApplication sharedApplication] windows]objectAtIndex:1] contentView]subviews]lastObject]subviews]lastObject]subviews]lastObject]subviews]lastObject]subviews]);
}
}
}
Related
We all know how to add custom button (usually it's Done) above normal numeric pad on iPhone. There were few questions related to this:
how to get keyboard location in ios 8 & add DONE button on numberPad
Can't find keyplane that supports type 4 for keyboard iPhone-Portrait-NumberPad; using 3876877096_Portrait_iPhone-Simple-Pad_Default
they work fine before iOS9. iOS9 broke that existing keyboard view hierarchy and above mentioned solutions don't work anymore. I've spend few hours trying to figure out the difference, and decided to post it here as it might be useful for other people.
The difference from the solution that worked for iOS7-8 is the following:
// Note index 2 here! In pre-iOS8 keyboard view panel was under second window after UIWindow, in iOS9 - they put some other views on the place and shifted everything one element down.
UIWindow *tempWindow = [[[UIApplication sharedApplication] windows][2];
UIView *keyboard;
for (int i = 0; i < [tempWindow.subviews count]; i++)
{
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if ([[keyboard description] hasPrefix:#"<UIPeripheralHostView"] == YES)
{
[keyboard addSubview:doneButton];
}
}
This question already has an answer here:
iOS 5: Any way to prevent keyboard splitting?
(1 answer)
Closed 9 years ago.
Is there any way to turn off keyboard splitting programmatically.
from my little knowledge, you can't lock default iPad keyboard scrolling movement.
You can manage its other functionalities like keyboard type and you can also create custom uikeyboard.
Please check this post which is discussing about creating a custom uikeyboard
However, please take a look on this code and try to achieve your goal
//The UIWindow that contains the keyboard view - It some situations it will be better to actually
//iterate through each window to figure out where the keyboard is, but In my applications case
//I know that the second window has the keyboard so I just reference it directly
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
//Because we cant get access to the UIKeyboard throught the SDK we will just use UIView.
//UIKeyboard is a subclass of UIView anyways
UIView* keyboard;
//Iterate though each view inside of the selected Window
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
//Get a reference of the current view
keyboard = [tempWindow.subviews objectAtIndex:i];
//Check to see if the className of the view we have referenced is \"UIKeyboard\" if so then we found
//the keyboard view that we were looking for
if([[keyboard className] isEqualToString:#\"UIKeyboard\"] == YES)
{
//Keyboard is now a UIView reference to the UIKeyboard we want. From here we can add a subview
//to th keyboard like a new button
//Do what ever you want to do to your keyboard here...
}
}
I would like to make an extra button in the iPhone keyboard left bottom corner like on the photo bellow. Is it possible to do this ?
the only way to customize those buttons is to rebuild the keyboard itself.
http://www.raywenderlich.com/1063/ipad-for-iphone-developers-101-custom-input-view-tutorial
Ray has always got some good tutorials on iphone dev. being able to customize your inputView is only half the battle tho. You will then need to build the custom view. Likely you will want to emulate the existing keypad, with your custom button obviously.
as a side note. to dismiss the keyboard you need to resignFirstResponder via the first responder.
When you get that far, here is the code I use to do exactly that
#implementation UIView (FindAndResignFirstResponder)
- (BOOL)findAndResignFirstResponder
{
UIView *responder = [self findFirstResponder];
if (responder) {
[responder resignFirstResponder];
return YES;
}
return NO;
}
- (UIView*)findFirstResponder
{
if (self.isFirstResponder) {
return self;
}
for (UIView *subView in self.subviews) {
UIView *responder = [subView findFirstResponder];
if (responder != nil)
return responder;
}
return nil;
}
#end
call the if you have a hold of the superview of all your inputs, you can call findAndResignFirstResponder on that view.
Or as you can see the findAndResignFirstResponder calls resignFirstResponder on the "found" firstResponder. therefore if you have the first responder you can just resign it
No it is not. The Keyboard is owned by the system. You can change the kind of keyboard (normal, numeric, twitter etc), but you can't customise it. It is a question which is worth a +1
In my iPhone app, I have array of buttons that are dynamically generated based on user selection.
How do I distinguish selected button from others?
I want that when user select the other button the previously selected button should go back to its normal state in terms of its looks. I am unable to revert the previously selected buttons to its normal state.
Use tag to identify the button.
At the time of creating buttons you can assign tag as number to the button and use the same to identify.
yourButton.tag = intNumber;
You have an array of the buttons. You can loop through your array and check if it is the one that was clicked.
- (IBAction) buttonClicked:(id)sender {
for(int i; i < [array count]; i++){
if((UIButton *)sender == (UIButton *)[array objectAtIndex:i])
//do something
else
//do something else
}
Something like that.
Try setting tag for each button,using
yourButton.tag=intValue; //intValue>0
Your buttonAction should be as follows,
-(IBAction)buttonAction:(id)sender
Save the previously selected tag, and change the value accordingly.
you can loop through your subviews and set for all the old style:
- (void)highlightImgWithID:(int)packID {
[self.view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UIImageView class]]) {
[(UIImageView*)obj setHighlighted:([obj tag] == IDtoSelectNext)];
}
}];
}
The sample is how I currently implement it in my App with UIImageView's you can change it to work with buttons.
I have noticed, in one of my views in an iPad app I am building the next button on the keyboard goes through all the UITextFields from left to right down the screen.
Is it possible somehow to make it go top to bottom then right, top to bottom?
So say I have to two long columns of text fields, I wan to go top to bottom not left to right, make sense?
Any help appreciated, thanks.
I don't think there is a way through IB, but you can do this way in code. You're not actually tabbing, you'd be using the return key.
Put this in your UITextField's delegate:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
BOOL shouldChangeText = YES;
if ([text isEqualToString:#"\n"]) {
// Find the next entry field
BOOL isLastField = YES;
for (UIView *view in [self entryFields]) {
if (view.tag == (textView.tag + 1)) {
[view becomeFirstResponder];
isLastField = NO;
break;
}
}
if (isLastField) {
[textView resignFirstResponder];
}
shouldChangeText = NO;
}
return shouldChangeText;
}
Found here: http://iphoneincubator.com/blog/tag/uitextfield
You'll want to implement UITextFieldDelegate's - (BOOL)textFieldShouldReturn:(UITextField *)textField method. An example of how to use this method to control the order is in this question.
I would like to elaborate on #sprocket's answer addressing the same issue. Just because something works out of the box doesn't mean you should stop thinking about a better way -- or even the right way -- of doing something. As he noticed the behavior is undocumented but fits our needs most of the time.
This wasn't enough for me though. Think of a RTL language and tabs would still tab left-to-right, not to mention the behavior is entirely different from simulator to device (device doesn't focus the first input upon tab). Most importantly though, Apple's undocumented implementation seems to only consider views currently installed in the view hierarchy.
Think of a form in form of (no pun intended) a table view. Each cell holds a single control, hence not all form elements may be visible at the same time. Apple would just cycle back up once you reached the bottommost (on screen!) control, instead of scrolling further down. This behavior is most definitely not what we desire.
So here's what I've come up with. Your form should be managed by a view controller, and view controllers are part of the responder chain. So you're perfectly free to implement the following methods:
#pragma mark - Key Commands
- (NSArray *)keyCommands
{
static NSArray *commands;
static dispatch_once_t once;
dispatch_once(&once, ^{
UIKeyCommand *const forward = [UIKeyCommand keyCommandWithInput:#"\t" modifierFlags:0 action:#selector(tabForward:)];
UIKeyCommand *const backward = [UIKeyCommand keyCommandWithInput:#"\t" modifierFlags:UIKeyModifierShift action:#selector(tabBackward:)];
commands = #[forward, backward];
});
return commands;
}
- (void)tabForward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.firstObject becomeFirstResponder];
}
- (void)tabBackward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls.reverseObjectEnumerator) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.lastObject becomeFirstResponder];
}
Additional logic for scrolling offscreen responders visible beforehand may apply.
Another advantage of this approach is that you don't need to subclass all kinds of controls you may want to display (like UITextFields) but can instead manage the logic at controller level, where, let's be honest, is the right place to do so.