iOS number pad keyboard with ability to switch on text keyboard - ios

I have a text field that I want to have a keyboard like this when user start typing:
please also see this video: https://youtu.be/iU_jocny3N0
As you can see in this video there is a "ABC" key that helps user to switch from number pad to text. and also when press "123" in text the keyboard switchs from text to number pad. I am wondering how they do this?
The only solution that I found was adding a subview to keyboard like what described here:
Adding Done Button to Only Number Pad Keyboard on iPhone
but this way may not work when user uses custom keyboards. and also do not works for switching from text to number pad.
Or as another solution I know accessoryInputView but this is not like the video. It adds a toolbar above the keyboard.
Does someone knows the solutions that is used in this video?

I have added comma button to the keyboard,
Keyboard is also a simple UIView Which contains Controls
NOTE: This is old code was working in my old project Not tested in new projects
- (void) keyboardWillShow:(NSNotification *)note {
// create custom button
dispatch_async(dispatch_get_main_queue(), ^{
// Some code
UITextField *txt = (UITextField *)[self.view findFirstResponder];
if (txt.keyboardType == UIKeyboardTypeDecimalPad) {
UIButton * btnComma = [UIButton buttonWithType:UIButtonTypeCustom];
[btnComma setTag:15000];
UIView* keyboard = [self findKeyboard];
// btnComma.frame = CGRectMake(0, 162, 126, 54);
btnComma.frame = [self findKeySizeForView:keyboard];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
[btnComma setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 20, 0)];
}
[btnComma setBackgroundColor:[UIColor colorWithHexString:#"CBD0D6"]];
btnComma.adjustsImageWhenHighlighted = NO;
[btnComma setTitle:#"." forState:UIControlStateNormal];
[btnComma setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnComma.titleLabel setFont:[UIFont systemFontOfSize:35.0f]];
[btnComma addTarget:self action:#selector(commaBtnTapped) forControlEvents:UIControlEventTouchUpInside];
[keyboard addSubview:btnComma];
btnComma = nil;
}
});
}
- (UIView *) viewWithPrefix:(NSString *)prefix inView:(UIView *)view {
for (UIView *subview in view.subviews) {
if ([[subview description] hasPrefix:prefix]) {
return subview;
}
}
return nil;
}
This method for finding keyboard from UIWindow
- (UIView *) findKeyboard {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
UIView *inputSetContainer = [self viewWithPrefix:#"<UIInputSetContainerView" inView:window];
if (inputSetContainer) {
UIView *inputSetHost = [self viewWithPrefix:#"<UIInputSetHostView" inView:inputSetContainer];
if (inputSetHost) {
UIView *kbinputbackdrop = [self viewWithPrefix:#"<_UIKBCompatInput" inView:inputSetHost];
if (kbinputbackdrop) {
UIView *theKeyboard = [self viewWithPrefix:#"<UIKeyboard" inView:kbinputbackdrop];
return theKeyboard;
}
}
}
}
return nil;
}
and For finding size of bottom right button
- (CGRect ) findKeySizeForView:(UIView *)view {
if (view != nil) {
UIView *uiKeyboardImpl = [self viewWithPrefix:#"<UIKeyboardImpl" inView:view];
if (uiKeyboardImpl != nil) {
UIView *uiKeyboardLayoutStar = [self viewWithPrefix:#"<UIKeyboardLayoutStar" inView:uiKeyboardImpl];
if (uiKeyboardLayoutStar != nil) {
UIView *uiKBKeyplaneView = [self viewWithPrefix:#"<UIKBKeyplaneView" inView:uiKeyboardLayoutStar];
if (uiKBKeyplaneView != nil) {
for (view in [uiKBKeyplaneView subviews]) {
CGPoint pointOrigin = view.layer.frame.origin;
if (pointOrigin.x <= 0 && pointOrigin.y == uiKBKeyplaneView.frame.size.height - view.frame.size.height && [[view description] hasPrefix:#"<UIKBKeyView"])
return view.layer.frame;
}
}
}
}
}
return CGRectZero;
}

Related

iOS: Handling long press and drag to select another button. (Like the keyboard)

I'm having a hard time finding the right documentation for how to handle touch events in order to support similar behavior to the keyboard.
What I want is a button that when I long press it, it shows a custom view controller above the button, but I want the user to be able to drag their finger to one of the other buttons (without taking their finger off the screen).
I have the button with a long press and it's custom view controller all setup and working. What I can't figure is how to support dragging from the first button over to the other button in the view controller to be able to select it.
I've tried using a subclassed UIButton where I tried this:
[self addTarget:self action:#selector(onDragOver:) forControlEvents:UIControlEventTouchDragEnter];
But that doesn't work.
I also found this question How to track button selection after long press? which is precisely the functionality I'm trying to duplicate. But there are no answers.
Here's my solution. The trick is you have to use hitTest:.
First you add a gesture recognizer to the button that is a normal button - the button that you want to open a context menu / custom view controller.
Then in your gesture recognizer callback, you use hitTest: to figure out if the user is over a custom button of yours and update it's state manually.
- (id) init {
//add a long press gesture recognizer
UILongPressureGestureRecognizer * gesture = [[UILongPressureGestureRecognizer alloc] initWithTarget:self action:#selector(onLongTap:)];
[self.myButton addGestureRecognizer:gesture];
}
- (void) onLongTap:(UIGestureRecognizer *) gesture {
if(gesture.state == UIGestureRecognizerStateBegan) {
//display your view controller / context menu over the button
}
if(gesture.state == UIGestureRecognizerStateEnded) {
//gesture stopped, use hitTest to find if their finger was over a context button
CGPoint location = [gesture locationInView:self.view];
CGPoint superviewLocation = [self.view.superview convertPoint:location fromView:self.view];
UIView * view = [self.view.superview hitTest:superviewLocation withEvent:nil];
if([view isKindOfClass:[MMContextMenuButton class]]) {
//their finger was over my custom button, tell the button to send actions
MMContextMenuButton * button = (MMContextMenuButton *) view;
[self hideAndSendControlEvents:UIControlEventTouchUpInside];
if(self.draggedContextMenuButton == button) {
self.draggedContextMenuButton = nil;
}
}
if(self.draggedContextMenuButton) {
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
self.draggedContextMenuButton = nil;
}
if(gesture.state == UIGestureRecognizerStateChanged) {
//gesture changed, use hitTest to see if their finger
//is over a button. Manually have to tell the button
//that it should update it's state.
CGPoint location = [gesture locationInView:self.view];
CGPoint superviewLocation = [self.view.superview convertPoint:location fromView:self.view];
UIView * view = [self.view.superview hitTest:superviewLocation withEvent:nil];
if([view isKindOfClass[MMContextMenuButton class]]) {
MMContextMenuButton * button = (MMContextMenuButton *) view;
if(self.draggedContextMenuButton != button) {
[self.draggedContextMenuButton dragOut];
}
self.draggedContextMenuButton = button;
[button dragOver];
}
}
}
//////////////
#import "MMContextMenuButton.h"
#import "MMContextMenus.h"
#implementation MMContextMenuButton
- (id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
self.layer.cornerRadius = 4;
self.adjustsImageWhenHighlighted = FALSE;
self.adjustsImageWhenDisabled = FALSE;
self.backgroundColor = [UIColor clearColor];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[self setTitleColor:[UIColor colorWithRed:0.435 green:0.745 blue:0.867 alpha:1] forState:UIControlStateNormal];
[self addTarget:self action:#selector(onHighlight:) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:#selector(onRelease:) forControlEvents:UIControlEventTouchUpOutside&UIControlEventTouchUpOutside];
return self;
}
- (void) onHighlight:(id) sender {
self.backgroundColor = [UIColor colorWithRed:0.435 green:0.745 blue:0.867 alpha:1];
}
- (void) onRelease:(id) sender {
self.backgroundColor = [UIColor clearColor];
}
- (void) hideAndSendControlEvents:(UIControlEvents) events {
[self dragOut];
[self sendActionsForControlEvents:events];
[[MMContextMenus instance] hideContextMenus];
}
- (void) dragOver {
self.highlighted = TRUE;
self.backgroundColor = [UIColor colorWithRed:0.435 green:0.745 blue:0.867 alpha:1];
}
- (void) dragOut {
self.highlighted = FALSE;
self.backgroundColor = [UIColor clearColor];
}
#end

How can i change action of the button "return" on the keyboard on Xcode?

i need to change the text of the button "return" on my keyboard,and i even need to change its action.
The action should be a new paragraph.
Can you help me?
You cannot rename the Return button to any custom text
Some default values thatThe return key can take are
typedef enum : NSInteger {
UIReturnKeyDefault,
UIReturnKeyGo,
UIReturnKeyGoogle,
UIReturnKeyJoin,
UIReturnKeyNext,
UIReturnKeyRoute,
UIReturnKeySearch,
UIReturnKeySend,
UIReturnKeyYahoo,
UIReturnKeyDone,
UIReturnKeyEmergencyCall,
} UIReturnKeyType;
where Default is "return" others are Go, Google, Yahoo as is.
look here.
And for capturing the return Event you can use the textView Delegate method
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
NSLog(#"Pressed Return Key");
} else {
NSLog(#"Pressed Any Other Key");
}
return YES;
}
UITextField has this delegate method that you can implement, and get's called when you press return on the keyboard:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
You can add a new line char "\n" to the textView text and it would go to next line.
UITextView it's suppose to work like that where it would go to a new line when you press Return.
click and set your keyword here
[textField setReturnKeyType:UIReturnKeyDone];
for keyboard implement the protocol in your class, set
textfield.delegate = self;
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
// write you code here what you want .
return YES;
}
refer this if you want to UITextView How to dismiss keyboard for UITextView with return key?
Here is the way to add custom button over the keyboard. But apple could reject your app so be careful.
- (void)viewWillAppear:(BOOL)animtated {
// Register the observer for the keyboardWillShow event
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardDidShowNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animtated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillShow:(NSNotification *)notification {
// create custom buttom
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(self.view.frame.size.width- 100, self.view.frame.size.height - 200.0f, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton addTarget:self action:#selector(addParaGraph:) forControlEvents:UIControlEventTouchUpInside];
[doneButton setBackgroundColor:[UIColor redColor]];
[doneButton setTitle:#"Add Paragraph" forState:UIControlStateNormal];
[doneButton addTarget:self action:#selector(textFieldShouldReturn:) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
UIWindow *tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
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];
//}
}
}
- (void)addParaGraph:(id)sender{
// Write here you code to add new paragraph
}
-(BOOL)textFieldShouldReturn:(UITextField *)theTextField {
// Set the FirstResponder of the UITextField on the layout
[theTextField resignFirstResponder];
return YES;
}
Swift 3
let addressTextField = UITextField()
addressTextField.placeholder = "Search or enter website name"
addressTextField.layer.borderColor = UIColor.gray.cgColor
addressTextField.layer.borderWidth = 1.0
addressTextField.returnKeyType = .go
view.addSubview(addressTextField)
addressTextField.delegate = self
extension YourNaneController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}

Disable interaction for views behind background image

To show a help view I've put an UIImageView which behind has some UIButtons. How can I disable user interaction of these buttons? If I touch this image where buttons are behind, they responds to touch events.
CODE FOR IMAGE BACKGROUND:
self.helpBackground = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
self.helpBackground.backgroundColor = [UIColor colorWithWhite:0 alpha:0.75];
self.helpBackground.hidden = YES;
[self.view addSubview:self.helpBackground];
I've used self.helpBackground.userInteractionEnabled = NO; but didn't work.
Thanks.
Put your buttons in a array and loop through them and disable them:
NSArray *buttonsArray = #[yourButton1, yourButton2];
for (UIButton *button in buttonsArray) {
button.enabled = NO;
}
And when you want them enabled just loop again and set enabled to YES
Keep a Tag to your helpView(imageview) and add the following code
for (UIView *view in self.view.subviews) {
if (view.tag != yourViewTag) {
view.userInteractionEnabled = NO;
}
}
And after removing the help screen use the following code
for (UIView *view in self.view.subviews) {
view.userInteractionEnabled = YES;
}
you can try below solution..When help imageview is appearing
for (UIView *view in [self.view subviews])
{
if (view isKindOfClass:[UIButton Class])
{
view.userInteractionEnabled = NO;
}
else
{
view.userInteractionEnabled = YES;
}
}
////After dismissing the help screen you can
for (UIView *view in [self.view subviews])
{
if (view isKindOfClass:[UIButton Class])
{
view.userInteractionEnabled = YES;
}
}
////(OR) Simply do as below
self.view.userInteractionEnabled=YES;
Hope it helps you..
You can create a method that disables user interaction for all views that are under your helpBackground:
- (void)disableUserInteractionForViewsUnderView:(UIView *)view
{
CGRect area = view.frame;
for (UIView *underView in [self.view subviews]) {
if(CGRectContainsRect(area, underView.frame))
underView.userInteractionEnabled = NO;
}
}
and after that you call it where you need it:
[self disableUserInteractionForViewsUnderView:self.helpBackground];
EDIT
I've created a UIViewController category gist on github.com. You can find it here: https://gist.github.com/alexcristea/0244b50e503e8bf4f25d
You can use it like this:
[self enumerateViewsPlacedUnderView:self.helpBackground usingBlock:^(UIView *view) {
if ([view isKindOfClass:[UIButton class]]) {
view.userInteractionEnabled = NO;
}
}];

Detect Selected State of UIButton iOS

How can I detect the selected state of a uibutton?
I have 7 buttons and I have made them to be able to toggle or select multiple buttons at a time.
I want to be able to tell which buttons are in a selected state when I push the done button.
So if M, T and W are selected then I want to be able to detect that when pushing done.
I currently put a tag on the button and then call a method to unselect or select multiple buttons.
self.repeatOccurrenceFrequencyWeeklyTF = [[UITextField alloc]init];
self.repeatOccurrenceFrequencyWeeklyTF.frame = CGRectMake(80, 80, 32, 32);
self.repeatOccurrenceFrequencyWeeklyTF.delegate = self;
self.repeatOccurrenceFrequencyWeeklyTF.background = [UIImage imageNamed:#"repeatWeekly"];
self.repeatOccurrenceFrequencyWeeklyTF.font = [UIFont fontWithName:#"SegoeWP" size:15];
self.repeatOccurrenceFrequencyWeeklyTF.textColor = [UIColor appGreyText];
[self.repeatOccurrenceFrequencyWeeklyTF setValue:[UIColor colorWithRed:153/255.0 green:153/255.0 blue:153/255.0 alpha:1.0] forKeyPath:#"_placeholderLabel.textColor"];
self.repeatOccurrenceFrequencyWeeklyTF.placeholder = #"1";
UIView *leftView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 12, self.repeatOccurrenceFrequencyWeeklyTF.frame.size.height)];
self.repeatOccurrenceFrequencyWeeklyTF.leftView = leftView1;
self.repeatOccurrenceFrequencyWeeklyTF.leftViewMode = UITextFieldViewModeAlways;
self.repeatOccurrenceFrequencyWeeklyTF.rightViewMode = UITextFieldViewModeAlways;
self.keyboardToolbar = [self createInputToolbar];
self.repeatOccurrenceFrequencyWeeklyTF.inputAccessoryView = self.keyboardToolbar;
self.repeatOccurrenceFrequencyWeeklyTF.delegate = self;
self.repeatOccurrenceFrequencyWeeklyTF.keyboardType = UIKeyboardTypeNumberPad;
self.repeatOccurrenceFrequencyWeeklyTF.enabled = NO;
[self.view addSubview:self.repeatOccurrenceFrequencyWeeklyTF];
// Now, in your button action handler, you can do something like this:
- (void)mondayButtonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
aButton.selected = !aButton.selected;
if(aButton.tag == 111) {
}
if(aButton.tag == 222) {
}
if(aButton.tag == 333) {
}
if(aButton.tag == 444) {
}
if(aButton.tag == 555) {
}
if(aButton.tag == 666) {
}
NSLog(#"dsfdfdfsdfs %ld", (long)aButton.tag);
[aButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
}
I would use a NS_ENUM (which helps to keep a nice and readable code) and a NSMutableArray to keep track of your selected buttons.
Declare a enum that looks something like this:
typedef NS_ENUM(NSInteger, Weekday) {
WeekdayMonday,
WeekdayTuesday,
WeekdayWednesday,
WeekdayThursday,
WeekdayFriday,
WeekdaySaturday,
WeekdaySunday
};
Then tag your buttons with the correct enum:
tuesdayButton.tag = WeekdayTuesday;
And check when you tap button if your enum exists in your array:
- (void)buttonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
if ([array containsObject:#(aButton.tag)]){ //exists, remove it from array
[array removeObjectIdenticalTo:#(aButton.tag)];
}
}else{
[array addObject:#(aButton.tag)];
}
}
A possibility is to create an NSMutableArray named selectedButton. Do like this:
- (void)mondayButtonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
aButton.selected = !aButton.selected;
if(!aButton.selected && selectedButton.containsObject(aButton.Tag)) {
[selectedButton removeObject:aButton.tag];
}
else if(aButton.selected && !selectedButton.containsObject(aButton.Tag)) {
[selectedButton addObject:aButton.tag];
}
// do your stuff here
}
Now on done button click you have all the button thats tags are selected will be trackable with selectedButton array.
You can use:
[self.view viewWithTag:yourTagHere]
you can use this :
for (UIButton *btn in [self.view subviews]) { // self.view (change it with your button superview)
if ([btn isKindOfClass:[UIButton class]] && [btn isSelected] == YES) {
// here you found the button which is selected
}
}
[self.view viewWithTag:yourTagHere] replace

Rectangular UISearchBar on iOS 7

I'm trying to make a UISearchBar rectangular instead of rounded, but all the solutions I found so far (mostly iterating through subviews) seem broken on iOS 7.
I did some research myself and as it turns out, it only has a UIView subview, which has additional subviews, a UISearchBarBackground and a UISearchBarTextField (both of them are private classes).
I tried
if ([view isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[view removeFromSuperview];
}
and
if ([view conformsToProtocol:#protocol(UITextInputTraits)]) {
#try {
[(UITextField *)view setBorderStyle:UITextBorderStyleRoundedRect];
}
#catch (NSException * e) {
// ignore exception
}
}
where view is the subview of that one UIView subview but none of them seems to work.
Try this... (I know it is also using subview but it is working in ios7)
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 20, 320, 49)];
[self.view addSubview:searchBar];
[self checkSubViewsOfView:searchBar WithTabIndex:#""];
and Add this method
-(void)checkSubViewsOfView:(UIView *)view WithTabIndex:(NSString *)strTab
{
if ([view isKindOfClass:NSClassFromString(#"UISearchBarTextField")])
{
view.layer.borderWidth = 1;
view.layer.borderColor = [[UIColor whiteColor] CGColor];
return;
}
for (UIView *vvv in view.subviews)
{
NSLog(#"%#%#",strTab,[vvv description]);
if (vvv.subviews > 0)
{
NSString *str = [NSString stringWithFormat:#"____%#",strTab];
[self checkSubViewsOfView:vvv WithTabIndex:str];
}
}
}
you can set the searchfield-background like this:
[self.searchBar setSearchFieldBackgroundImage:[[UIImage imageNamed:#"searchbar_stretch-0-10-0-10"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10)] forState:UIControlStateNormal];
and the searchbar-background like this:
[self.searchBar setBackgroundImage:[UIImage imageNamed:#"categories_navbar"]];

Resources