Have added a custom view consisting of buttons on top of the keyboard. The buttons are being displayed correctly but on tapping on the buttons, the underlying keys of the keyboard are pressed instead of the button actions.
UIWindow* tempWindow = [UIApplication sharedApplication].windows.lastObject;
for (UIView *keyboard in [tempWindow subviews]) {
if ([[keyboard description] hasPrefix : #"<UIInputSetContainerView"]) {
for(int i = 0 ; i < [keyboard.subviews count] ; i++)
{
UIView* hostkeyboard = [keyboard.subviews objectAtIndex:i];
if([[hostkeyboard description] hasPrefix:#"<UIInputSetHost"] == YES){
[hostkeyboard addSubview:extraRow];
[hostkeyboard bringSubviewToFront:extraRow];
}
}
}
}
extraRow is the UIView consisting of buttons.
Is there anything missing ?
You could do just add a custom view to the keyboard as an inputAccessoryView. Then it just assign the button the correct target you want it to fire when clicked on
- (void)textFieldDidBeginEditing:(UITextField *)textField {
UIView * theView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
[theView setBackgroundColor: [UIColor greyColor]];
UITextField * txtTest = [[UITextField alloc] initWithFrame:CGRectMake(0, 5, theView.frame.size.width, 60)];
UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 65, 100, 30)];
[btn setTitle:#"Click my Button" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(alert:) forControlEvents:UIControlEventTouchUpInside];
// Just put this to see the items or customize the color
[txtTest setBackgroundColor:[UIColor whiteColor]];
[btn setBackgroundColor:[UIColor blueColor]];
// Need this to add it to the view
[theView addSubview:txtTest];
[theView addSubview:btn];
textField.inputAccessoryView = theView;
}
One thing you might want to consider is setting the extraRow's exclusiveTouch property to YES. As a disclaimer I haven't tried this example myself but I think the problem you are having is due to the view passing along the touch event.
Im trying to change the background color of the UITextField inside of an UISearchBar. To do this, I have tried the following:
-This simple one-liner of code:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor redColor]];
This for loop:
for (UIView *subView in _searchBar.subviews) {
for(id field in subView.subviews){
if ([field isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)field;
[textField setBackgroundColor:[UIColor grayColor]];
}
}
}
and this code:
UITextField *txfSearchField = [_searchBar valueForKey:#"_searchField"];
txfSearchField.backgroundColor = [UIColor redColor];
I'd like to avoid changing the background image of the UISearchBar, so what's the new solution for iOS8? I've found no working answer on stack.
Try as I might, I can't solve a UISegmentedControl bug for an iOS7 iPhone app.
When I create the segmented control, I use this code:
NSArray *segmentedControlItemArray = [NSArray arrayWithObjects: #"Nominal:\n27 inch", #"Actual:\n700c x 23mm", #"Actual:\n700c x 20mm", nil];
_wheelDiameterSegmentedControl = [[UISegmentedControl alloc] initWithItems:segmentedControlItemArray];
_wheelDiameterSegmentedControl.frame = CGRectMake(0, 102, 290, 50);
_wheelDiameterSegmentedControl.selectedSegmentIndex = 0;
_wheelDiameterSegmentedControl.tintColor = [UIColor colorWithRed:0.35 green:0.4 blue:0.9 alpha:1.0];
for (id segment in [_wheelDiameterSegmentedControl subviews]) {
for (id label in [segment subviews]) {
if ([label isKindOfClass:[UILabel class]]) {
UILabel *titleLabel = (UILabel *) label;
titleLabel.numberOfLines = 0;
}
}
}
[_wheelDiameterSegmentedControl addTarget:self
action:#selector(pickOne:)
forControlEvents:UIControlEventValueChanged];
[_wheelDiameterMenuContainer addSubview:_wheelDiameterSegmentedControl];
Sadly, I can't post images, or I would show you a picture of exactly the control I want: each of the segments in the UISegmented Control has two lines of text, with a line break exactly where I asked for it.
On rotation, though, I'd like to keep the segmented control full-width, and the line breaks look silly in segments that wide. So, in willAnimateRotationToInterfaceOrientation, I've included the following code, with no line breaks in the strings:
[_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 450, 50)];
[_wheelDiameterSegmentedControl setTitle:#"Nominal: 27 inch" forSegmentAtIndex:0];
[_wheelDiameterSegmentedControl setTitle:#"Actual: 700c x 23mm" forSegmentAtIndex:1];
[_wheelDiameterSegmentedControl setTitle:#"Actual: 700c x 20mm" forSegmentAtIndex:2];
And once again, if I could insert an image, I would show you an image of exactly what I want: a wide UISegmented Control with no line breaks in the labels (1 line of text per label).
Here's where I run in to trouble. My choices, when I rotate back to portrait, seem to be:
1 line of label text, truncated, with the format
"Actual: 7..."
when I just reset the size of the UISegmentedControl using
[_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 290, 50)];
2 lines of label text, truncated, with the format
"Actual:
700c x ..."
when I reset the size and also reset the string values and rerun the loop of code that sets the label's numberOfLines to 2, using
NSArray *segmentedControlItemArray = [NSArray arrayWithObjects: #"Nominal:\n27 inch", #"Actual:\n700c x 23mm", #"Actual:\n700c x 20mm", nil];
[_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:0] forSegmentAtIndex:0];
[_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:1] forSegmentAtIndex:1];
[_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:2] forSegmentAtIndex:2];
for (id segment in [_wheelDiameterSegmentedControl subviews]) {
for (id label in [segment subviews]) {
if ([label isKindOfClass:[UILabel class]]) {
UILabel *titleLabel = (UILabel *) label;
titleLabel.numberOfLines = 2;
}
}
}
[_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 290, 50)];
3 lines of label text, with the format
"Actual:
700c x
20mm"
which is what I get when I replace the forced numberOfLines = 2 above with the numberOfLines = 0 that worked when I set up the UISegmentedControl in the first place.
What I'd like is what I get when I create the control, which is
"Actual:
700c x 20mm"
But no matter what I've tried (putting the string and numberOfLines code into willRotateToInterfaceOrientation or didRotateFromInterfaceOrientation; re-setting the frame of the UISegmentedControl before changing the text; re-setting the frame after changing the text...), I can't get my nice, neat, two-line label back. What am I missing here?
Aha! Something about how the OS is handling the size of the label when it rotates is different from how it handles the label when it's created. So I forced the size of the frame of the label, using
for (id segment in [_wheelDiameterSegmentedControl subviews]) {
for (id label in [segment subviews]) {
if ([label isKindOfClass:[UILabel class]]) {
UILabel *titleLabel = (UILabel *) label;
//inserting line here, to make the frame behave nicely:
//
titleLabel.frame = CGRectMake(0, 0, 97, 50);
//
//continuing as before
titleLabel.numberOfLines = 0;
}
}
}
and now it displays exactly as I want/expect. Huzzah!
If you're just trying to get two (or more) lines of text in your UISegmentedControl. Using Herzian's amazing technology! Here's just another code example, that may help people...
self.yourSlider .. set the height manually (can't easily do it in XIB)
// now use amazing Herzian technology...
for (id segment in [self.yourSlider subviews])
for (id label in [segment subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
UILabel *titleLabel = (UILabel *) label;
titleLabel .. set the width to say 80, per your layout;
(the width us typically too low)
titleLabel.numberOfLines = 0;
}
}
thank you so much, again.
working code in ios 7 :
I have a segment controller with four segments and I need it in 2 lines for text. So I have added UILabel as a subview in segment of UISegmentedControl and it is working good. I have tried all other ways but in ios 7 and ios 8 it is working good right now.
for(int k =0;k<4;k++)
{
NSString *text = #"title name";
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(10,2, (self.segmentcontroll.frame.size.width/4), 34);
label.font = [UIFont fontWithName:#"HelveticaNeue" size:12.0];
label.textColor = [UIColor whiteColor];
label.text = text;
label.numberOfLines = 0;
label.textAlignment = NSTextAlignmentCenter;
[label sizeToFit];
[[[self.segmentcontroll subviews] objectAtIndex:k] addSubview:label];
}
And Herzian's solution as a category if anyone wants it. Remember to call it in VWA instead of VDL so it happens after autosizing / rotation
#import "UISegmentedControl+MultiLine.h"
#implementation UISegmentedControl (MultiLine)
-(void)setupMultiLine
{
self.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
self.frame.size.width,
self.frame.size.height*1.6);
for (id segment in self.subviews)
{
for (id label in [segment subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
UILabel *titleLabel = (UILabel*) label;
titleLabel.frame = CGRectMake(0,
0,
titleLabel.frame.size.width,
titleLabel.frame.size.height*1.6);
titleLabel.numberOfLines = 0;
}
}
}
}
#end
The problem I'm having is that when a user touches into the search bar the keyboard appears fine. Then when the presentQR method (see below) is called and then dismissed and then the searchbar is touched the keyboard appears as shown in the screenshot where it is offset. This is iOS7; not sure if that matters though.
I'm adding a UISearchbar using the following code:
// search bar
UIView *searchBarView = [[UIView alloc] initWithFrame:CGRectMake(90.0, 0.0, 200.0, 44.0)];
searchBarView.autoresizingMask = 0;
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 190, 40)];
searchBar.backgroundImage = [[UIImage alloc] init];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.navigationItem.titleView = searchBar;
searchBar.delegate = self;
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],UITextAttributeTextColor,[UIColor whiteColor],UITextAttributeTextShadowColor,[NSValue valueWithUIOffset:UIOffsetMake(0, -1)],UITextAttributeTextShadowOffset, nil] forState:UIControlStateNormal];
UITextField *textfield = [[UITextField alloc] init];
searchBar.placeholder = #"City Search";
// hide magnifying glass
textfield = nil;
for (UIView* subView in searchBar.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
textfield = (UITextField*)subView;
[(UITextField*)subView setTextColor:[UIColor whiteColor]];
[(UITextField*)subView setFont:[UIFont fontWithName:#"DIN-Regular" size:18]];
textfield.leftViewMode = UITextFieldViewModeNever;
textfield.rightViewMode = UITextFieldViewModeAlways;
break;
}
}
UIButton *cancelButton;
for (id button in searchBar.subviews)
{
if ([button isKindOfClass:[UIButton class]])
{
cancelButton=(UIButton*)button;
break;
}
}
[searchBar addSubview:textfield];
[searchBarView addSubview:searchBar];
self.navigationItem.titleView = searchBarView;
-(void)presentQR {
QRReaderViewController *qr = [[QRReaderViewController alloc]initWithNibName:#"QRReaderViewController" bundle:nil];
UIButton *removeQRBtn=[UIButton buttonWithType:UIButtonTypeCustom];
removeQRBtn.frame=CGRectMake(260, 10, 60, 40);
[removeQRBtn addTarget:self action:#selector(removeQR) forControlEvents:UIControlEventTouchDown];
[removeQRBtn setImage:[UIImage imageNamed:#"qrcode.png"] forState:0];
[qr.view addSubview:removeQRBtn];
qr.view.backgroundColor = customColorGrey;
qr.modalPresentationStyle = UIModalTransitionStyleCrossDissolve;
// [self presentModalViewController:qr animated:YES];
[self presentViewController:qr animated:YES completion:nil];
}
-(void)removeQR {
// [self dismissModalViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
1st Make sure that in QRReaderViewController there is nothing like reframing window or such. There might be an element conflicting with UIWindow preventing keyboard to be shown correctly. (e.g unbalanced orientation changes.)
2nd If you didn't find anything there you could try accessing the keyboard view using the following code and attempt to reset the frame. You could put this code in keyboardWillShow method (need to register for the notification)
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/c/data/UIKeyboardWillShowNotification
PS. I would suggest to just log the keyboard frame so you know when it's changed.
Reframing Keyboard: Found here: https://stackoverflow.com/a/10957843/1017340
//The UIWindow that contains the keyboard view - It some situations it will be better to actually
//You need to 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 UIPeripheral throughout the SDK we will just use UIView.
//UIPeripheral 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];
//Assuming this is for 4.0+, In 3.0 you would use "<UIKeyboard"
if([[keyboard description] hasPrefix:#"<UIPeripheral"] == YES)
{
NSLog(#"Keyboard Frame: %#",NSStringFromCGRect(keyboard.frame));
//HERE : try reframing the keyboard
//[keyboard setFrame:CGRectMake(...)]; /*NOT TESTED NOT RECOMMENDED*/
}
}
I have dynamic UIButtons with subview is UIlabel.
My requirement is to display one label text in one button first time, after based on user selection(long press on the button) need to update the particular button subview label text and remove rest of the button subview label text.
I tried in this way
for (int i=0; i < [arr count]; i++)
{
UILabel *myLbl = [[UILabel alloc] initWithFrame:CGRectMake(30, 70, 60, 21)];
if (myissue.tag ==1) {
myLbl.text = #"Default";
}else {
myLbl.text = #"";
}
myLbl.backgroundColor = [UIColor clearColor];
myLbl.textColor = [UIColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:1.0];
[myLbl setFont:[UIFont fontWithName:#"Helvetica" size:12]];
myLbl.textAlignment = NSTextAlignmentCenter;
myLbl.tag = i+1;
[myButton addSubview:defaultLbl];
[myLbl release];
}
And for retrieving the UILabel text
- (void)longPressTap:(UILongPressGestureRecognizer *)sender
{
if ([recognizer.view tag]) {
for (UIButton *btn in scrollView.subviews) {
UIButton *btnTag = (UIButton *)btn;
NSLog(#"--sv:%#", btn.subviews);
if (recognizer.view.tag == btnTag.tag){
[[btn.subviews objectAtIndex:3] text] ;
}else {
[[btn.subviews objectAtIndex:3] textAttributesForNil] ;
}
}
}
}
}
my problem is i was not able to selected button subview label text and removing rest of the button label text.
please help me.
You shouldnt need to add a label as a subview for a button, buttons already have their own text label that can be set using [button setTitle:(NSString *) forState:(UIControlState)]
and to remove the text just set seTitle:#""