Моделирование кнопки отмены в UISearchBar

Больше не осталось проблем, просто добавили 9 якорей вместо div и добавили в css a {display: content}, и это работает для любого браузера

28
задан Cœur 31 December 2018 в 18:45
поделиться

9 ответов

То, что вы хотите сделать, довольно сложно. Нет встроенного крючка, чтобы попасть на кнопку отмены.

Однако, есть несколько вариантов, если вы хотите, чтобы Джимми открыл капот.

Во-первых, UISearchBar - это UIView, а кнопка «Отмена» - это также представление, которое добавляется в строку поиска как подпредставление, как и следовало ожидать.

Я немного поэкспериментировал и могу сказать, что когда кнопка находится на экране, она имеет размер 48,30.

Таким образом, в viewWillAppear вы можете сделать что-то вроде этого:

  1. Найдите представление кнопки отмены в [subviews searchBar], найдя один с размером 48,30. (Кажется, есть только один - это может измениться ...) Вы можете быть вдвойне осторожны и искать тот, который находится приблизительно в правильном положении (отличается в альбомной и портретной ориентации).

  2. Добавить подпредставление для кнопки отмены.

  3. Подвид должен быть UIControl (чтобы можно было включить enabled = NO, чтобы убедиться, что сенсорные события попадают на фактическую кнопку отмены)

  4. Он должен иметь правильный цвет и закругленные углы; вам нужно будет придумать размер по причинам, которые я еще не понимаю (кажется, 55,30 работает)

  5. Это будет работать, если searchBar.showsCancelButton всегда YES; если вы хотите, чтобы оно исчезло, когда строка редактирования не редактируется, вам нужно будет найти ловушку для добавления наложения при каждом появлении кнопки отмены.

  6. Как видите, это некрасивое возиться. Делайте это с широко открытыми глазами.

13
ответ дан Amagrammer 28 November 2019 в 02:15
поделиться
UISearchBar *searchBar;
[searchBar setShowsCancelButton:YES animated:YES];

UIButton *cancelButton = 
YES == [searchBar respondsToSelector:NSSelectorFromString(@"cancelButton")] ? 
[searchBar valueForKeyPath:@"_cancelButton"] : nil;

cancelButton.titleEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10);
[cancelButton setTitle:@"New :)" forState:UIControlStateNormal];
0
ответ дан Roman Solodyashkin 28 November 2019 в 02:15
поделиться

Глупый путь

for(id cc in [SearchBar subviews])
{
    if([cc isKindOfClass:[UIButton class]])
    {
        UIButton *btn = (UIButton *)cc;
        ......
        Do whatever you want
        .......        
    }
}
0
ответ дан LucKy_one 28 November 2019 в 02:15
поделиться

Swift 2.1.1:

Нет простого способа подключить и стилизовать панель поиска, вам нужно вручную извлечь подпредставление из панели поиска и затем применить ваши изменения.

var cancelButton: UIButton
let topView: UIView = self.customSearchController.customSearchBar.subviews[0] as UIView
for subView in topView.subviews {
 if subView.isKindOfClass(NSClassFromString("UINavigationButton")!) {
    cancelButton = subView as! UIButton
    cancelButton.enabled = true
    cancelButton.setTitle("TestTitle", forState: UIControlState.Normal) // Change to set the title
    cancelButton.setBackgroundImage(UIImage(named: "ImageName"), forState: .Normal) // Change this to set a custom cancel button image, set the title to "" to remove 'Cancel' text
   }
}
1
ответ дан Elliott Davies 28 November 2019 в 02:15
поделиться

Я дам подробный ответ относительно техники UIAppearance. Во-первых, вы должны понимать, что кнопка отмены является частной кнопкой UINavigationButton: UIButton. После некоторой проверки кажется, что UINavigationButton будет реагировать на эти селекторы UIAppearance:

// inherited from UINavigationButton
@selector(setTintColor:)
@selector(setBackgroundImage:forState:style:barMetrics:)
@selector(setBackgroundImage:forState:barMetrics:)
@selector(setTitleTextAttributes:forState:)
@selector(setBackgroundVerticalPositionAdjustment:forBarMetrics:)
@selector(setTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundImage:forState:barMetrics:)
@selector(setBackButtonTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundVerticalPositionAdjustment:forBarMetrics:)

// inherited from UIButton
@selector(setTitle:forState:)

По совпадению, эти селекторы соответствуют селекторам UIBarButtonItem. Смысл в том, чтобы использовать два отдельных UIAppearance для обработки частного класса UINavigationButton.

/* dual appearance technique by Cœur to customize a UINavigationButton */
Class barClass = [UISearchBar self];

UIBarButtonItem<UIAppearance> *barButtonItemAppearanceInBar = [UIBarButtonItem appearanceWhenContainedIn:barClass, nil];
[barButtonItemAppearanceInBar setTintColor:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... style:... barMetrics:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setTitleTextAttributes:... forState:...];
[barButtonItemAppearanceInBar setBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setTitlePositionAdjustment:... forBarMetrics:...];
// only for a backButton in an UINavigationBar, not for a cancelButton in an UISearchBar
//[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...];
//[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...];
//[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...];

UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil];
// warning: doesn't work for iOS7+
[buttonAppearanceInBar setTitle:... forState:...];

Это позволит вам настроить кнопку «Отмена» так, как вы хотите.

4
ответ дан Cœur 28 November 2019 в 02:15
поделиться

После того, как вы инициализировали UISearchBar, вы можете исследовать его подпредставления и настроить каждый из них. Пример:

for (UIView *view in searchBar.subviews) {

    //if subview is the button
    if ([[view.class description] isEqualToString:@"UINavigationButton"]) {

        //change the button images and text for different states
        [((UIButton *)view) setEnabled:YES];
        [((UIButton *)view) setTitle:nil forState:UIControlStateNormal];
        [((UIButton *)view) setImage:[UIImage imageNamed:@"button image"] forState:UIControlStateNormal];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateSelected];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateHighlighted];

    //if the subview is the background
    }else if([[view.class description] isEqualToString:@"UISearchBarBackground"]) {

        //put a custom gradient overtop the background
        CAGradientLayer *gradient = [CAGradientLayer layer];
        gradient.frame = view.bounds;
        gradient.colors = [NSArray arrayWithObjects:(id)[[some uicolor] CGColor], (id)[[another uicolor] CGColor], nil];
        [view.layer insertSublayer:gradient atIndex:0];

    //if the subview is the textfield
    }else if([[view.class description] isEqualToString:@"UISearchBarTextField"]){

        //change the text field if you wish

    }

}

Отлично сработало для меня! Особенно градиент:)

1
ответ дан яοвοτағτєяаււ 28 November 2019 в 02:15
поделиться

Для iOS 10 & выше, используйте следующий метод

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor blackColor]];
0
ответ дан 28 November 2019 в 02:15
поделиться

Вы можете найти кнопку отмены, перебирая вложенные представления строки поиска и проверяя тип класса (вместо размера):

UIButton *cancelButton = nil;
for(UIView *subView in yourSearchBar.subviews){
    if([subView isKindOfClass:UIButton.class]){
    cancelButton = (UIButton*)subView;
    }
}

А затем измените цвет оттенка:

[cancelButton setTintColor:[UIColor colorWithRed:145.0/255.0 green:159.0/255.0 blue:179.0/255.0 alpha:1.0]];
7
ответ дан 28 November 2019 в 02:15
поделиться

Ну, вот функция, которая может изменить ярлык кнопки Cancel. Измените ее, если хотите. Использование:

nStaticReplaceStringInView(mySearchBar, @"Cancel", @"NewCancelButtonLabel");

void nStaticReplaceStringInView(UIView * view, NSString * haystack, NSString * needle)
{
 for(int i=0; i<[view.subviews count]; i++)
 {
  nStaticReplaceStringInView([view.subviews objectAtIndex:i], haystack,needle);
 }
 if([view respondsToSelector:@selector(titleForState:)])
 {
  //NSLog(@"%@ || %@",[view titleForState:UIControlStateNormal], haystack);
  if(NSStrEq([view titleForState:UIControlStateNormal] , haystack))
  {
   [view setTitle: needle forState: UIControlStateNormal];
  }
 }
}
0
ответ дан 28 November 2019 в 02:15
поделиться