I have a UISearchBar whose appearance I want to customise. The suggestion in this post worked before the update to iOS 7. But now I'm not sure how to do it. I mainly want to customise the Cancel button. Does anybody know how?
You need to search for the button recursively. This should be a fail-safe way to do it:
- (void)viewDidLoad
{
[super viewDidLoad];
[self convertButtonTitle:#"Cancel" toTitle:#"Annuller" inView:self.searchBar];
}
- (void)convertButtonTitle:(NSString *)from toTitle:(NSString *)to inView:(UIView *)view
{
if ([view isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton *)view;
if ([[button titleForState:UIControlStateNormal] isEqualToString:from])
{
[button setTitle:to forState:UIControlStateNormal];
}
}
for (UIView *subview in view.subviews)
{
[self convertButtonTitle:from toTitle:to inView:subview];
}
}
I've tested this on iOS 7 only, but it works and should do so for iOS 6 too.
Related
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;
}
i wanted to change buttons color in action sheet so i wrote this code
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
for (UIView *_currentView in actionSheet.subviews) {
if ([_currentView isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)_currentView;
button.titleLabel.textColor = [UIColor darkGrayColor];
NSLog(#"%#",#"ahmed");
}
}
}
but nothing happen although i made delegate to self and called UIActionSheetDelegate .
although i have 6 buttons ,i see as this function wasn't be called at all
what is the problem?????
I would really like to change the color of the "Search" button on the keyboard to match the theme of my app. But if that is not possible, at least I would like to do
self.searchBar.keyboardAppearance = UIKeyboardAppearanceDark;
But that does not work because, as I guess, the searchBar is not a UITextField. So how might I do this successful? I mean, change the color of the "Search" on the keyboard: whether fully or just the dark theme.
For iOS 8 use
self.searchBar.keyboardAppearance = UIKeyboardAppearance.Dark
Try this, it works with IOS 6 , IOS 7 and IOS 8:
[self setKeyboardOnSearchBar:self.searchBar];
And the function:
-(void)setKeyboardOnSearchBar:(UISearchBar *)searchBar
{
for(UIView *subView in searchBar.subviews) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subView setKeyboardAppearance:UIKeyboardAppearanceAlert];
[(UITextField *)subView setReturnKeyType:UIReturnKeySearch];
} else {
for(UIView *subSubView in [subView subviews]) {
if([subSubView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subSubView setReturnKeyType:UIReturnKeySearch];
[(UITextField *)subSubView setKeyboardAppearance:UIKeyboardAppearanceAlert];
}
}
}
}
}
Try the following
for(UIView *subView in self.searchBar.subviews) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subView setKeyboardAppearance: UIKeyboardAppearanceDark];
}
}
Swift 4 update, iOS 11+ :
searchBar.keyboardAppearance = .dark
searchBar.keyboardAppearance = .light
searchBar.keyboardAppearance = .default
Swift 5, iOS 14:
If Search bar is present inside a specific view (eg- SearchBarView),
UITextField.appearance(whenContainedInInstancesOf: [SearchBarView.self]).keyboardAppearance = .dark
Will cause change only for the specific search bar inside the SearchBarView.
Else if you want to do for all Search Bars then,
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).keyboardAppearance = .dark
I am running this code, because I want to change something on all the buttons within my ViewController when it starts.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
int i = 1;
for (UIButton *btn in self.view.subviews)
{
NSLog(#"Count I - %d ", i);
//NSLog(#"Count I - %d - %#", i, btn.titleLabel.text);
i++;
}
}
The Output it:
2013-11-11 08:15:13.315 testingSingle[7876:a0b] Count I - 1
2013-11-11 08:15:13.317 testingSingle[7876:a0b] Count I - 2
Now this seems strange to me, because it is a new project and nothing has been dragged onto or even changed on the VC in the storyboard or in code - there is nothing to suggest that there 2 UIButtons.
How can I get this message to return 0 if this is the case? My app crashes because of this.
Changing your NSLog to
NSLog(#"%#", [btn class]);
gives the output
_UILayoutGuide
_UILayoutGuide
which shows that there are no buttons, but some other views (perhaps required for Autolayout).
for (UIButton *btn in self.view.subviews)
enumerates all subviews, it does not matter that the loop variable btw is
declared as UIButton *.
To handle only buttons, you have to test the class of each object:
for (UIView *subView in self.view.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)subView;
// Do something with btn ...
i++;
}
}
I created a search bar programmatically and added to my view using the codes below:
- (void)viewDidLoad
{
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(xPositionForSearchBar, yPositionForSearchBar, widthForSearchBar, heightForSearchBar)];
UIView *bg = [[searchBar subviews] objectAtIndex:0];
searchBar.delegate = self;
searchBar.placeholder = #"Search record";
for(UIView *view in searchBar.subviews){
if([view isKindOfClass:[UITextField class]]){
UITextField *tf = (UITextField *)view;
tf.delegate = self;
break;
}
}
[bg removeFromSuperview];
[self.view addSubview: searchBar];
}
The code is implemented with UISearchBarDelegate and UITextFieldDelegate.
I have tried using
- (void)searchBarCancelButtonClicked:(UISearchBar *)aSearchBar
{
NSLog(#"cancel clicked");
searchBar.text = #"";
[aSearchBar resignFirstResponder];
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
NSLog(#"clear");
[self performSelector:#selector(searchBarCancelButtonClicked:) withObject:searchBar afterDelay: 0.1];
return YES;
}
and yet, the text inside the searchBar is not cleared at all when i click on the "clear button" - a circle with a "X" inside.
The clear button works when I implemented it in IB. Wonder why?
Kindly advice, many thanks.
This might happen if you position your search bar out of the bounds of a parent view. Then, the touches aren't delivered to your searchBar properly. This also affects text editing controls like copy & paste.
I have checked your code it work fine on device as well as on simulator.