Изменение размера текстового поля UISearchBar TextField?

У меня есть UITableView с индексом сбоку; Я хочу добавить к нему UISearchBar, но индекс перекрывается с «x», чтобы очистить поиск. Я заметил, что в приложении «Контакты» размер текстового поля в UISearchBar изменен с учетом этого, но я не могу понять, как это сделать в моем собственном приложении.

Я пробовал следующее в моем viewDidLoad, но, похоже, это не работает.

UITextField * textField = (UITextField *)[[self.search subviews] objectAtIndex:0];
CGRect r = textField.frame;

[textField setFrame:CGRectMake(r.origin.x, r.origin.y, r.size.height, r.size.width-30)];

Любые идеи?


person Padraig    schedule 17.02.2009    source источник


Ответы (18)


это намного проще, чем все эти предложения. В конструкторе интерфейса вместо того, чтобы помещать панель поиска в качестве заголовка представления таблицы, вы можете поместить вместо этого представление. Затем поместите панель навигации внутрь этого представления. Возьмитесь за левый маркер изменения размера на панели навигации и потяните его вправо, пока ширина N B не станет всего 25 пикселей. Очистите заголовок в NB (дважды щелкните, чтобы выбрать его, затем удалите). Затем добавьте панель поиска в то же представление. Переместите его правый маркер изменения размера влево, отрегулируйте так, чтобы он упирался в букву N. Вот и все.

Вы также можете включить кнопку отмены, если хотите, и она также не будет перекрывать индекс (остается в строке поиска).

Судя по всему, табличное представление может иметь только 1 подвид в заголовке, поэтому вам нужно сначала поместить представление, затем NB и панель поиска внутри него.

ОБНОВЛЕНИЕ: см. Начало разработки iPhone в Apress, стр. 241 редакции SDK 3. Вы просто отключаете индекс во время поиска.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    if (isSearching) {
        return nil;
    }
    return keys;
}

Также говорят о добавлении лупы вверху индекса.

Отличная книга во всем.

person Mike    schedule 28.10.2009
comment
Отлично сработал - одно дополнение - к нашему табличному представлению применен некоторый настраиваемый стиль, и чтобы панель навигации и панель поиска выглядели одинаково, мне пришлось сделать родительский вид прозрачным (т.е. без фона) - поэтому, если что-то не так вполне соответствует попробуйте это. - person Joe; 12.05.2010
comment
Блестяще. Чистый блеск. Спасибо! - person hishamaus; 29.07.2013

Почему бы просто не уменьшить фактический UISearchBar по горизонтали и разместить (пустой) UINavigationBar справа от него? Они будут отображать точно такой же фон.

Лучше, чем взламывать внутренние объекты Apple, которые могут измениться.

Кроме того, при анимации ширины UISearchBar вы заметите, что внутреннее текстовое поле не анимируется вместе с ним. Вы можете исправить это, вызвав "layoutSubviews" UISearchBar в своем блоке анимации после изменения его кадра. (именно здесь он определяет размер внутреннего текстового поля)

person Nick Farina    schedule 26.02.2009
comment
Большое спасибо, чувак !!!! Я не мог понять, как заставить панель поиска оживить. layoutSubviews был ключевым. - person Meroon; 04.11.2009
comment
У меня был UISearchBar с правой стороны от UINavigationBar, и я анимировал его то же самое, что и приложение Safari. Этот совет по layoutSubview для UISearchBar был последним кусочком головоломки, заставившим его работать так же, как Safari. Нет необходимости искать во вложенных представлениях или что-то в этом роде, что не является правильным или чистым решением. Еще раз спасибо за правильный ответ. - person petert; 18.06.2010
comment
Это также решило проблему для меня простым и понятным способом. Спасибо! - person David Coufal; 03.07.2010

Хорошо, я нашел решение.

  1. Создайте подкласс UISearchBar
  2. Включите этот код в метод drawRect :.

    UITextView * textField = [self.subviews objectAtIndex:0];
    textField.frame = CGRectMake(5, 6, (310 - kRightSideMargin), 31); 
    
    [super drawRect:rect];
    

Примечание. KRightSideMargin - это константа, которую я установил в моем заголовочном файле; Я поставил 25.

Спасибо за предложения от всех остальных.

person Padraig    schedule 17.02.2009
comment
Я использую v3.0 iphone SDK, и размещение этого кода в drawRect не сработало. Что на самом деле сработало для меня, так это размещение этого кода в layoutSubviews. Не совсем уверен, почему - единственный вывод, который я могу сделать, это то, что в v2 есть изменение - ›v3 - person CVertex; 09.08.2009

Как указал Падрейг, все, что вам нужно сделать, это создать подкласс searchBar. Создайте свой подкласс UISearchBar и добавьте следующий код в метод layoutSubviews:

- (void)layoutSubviews
{
    UITextField *searchField;

    for(int i = 0; i < [self.subviews count]; i++)
    {
        if([[self.subviews objectAtIndex:i] isKindOfClass:[UITextField class]])
        {
            searchField = [self.subviews objectAtIndex:i];
        }
    }

    if(!(searchField == nil))
    {
        searchField.frame = CGRectMake(4, 5, 285, 30); 
    }
}

Это перебирает все подпредставления и проверяет их на соответствие типу UITextField. Таким образом, если он когда-либо переместится в свою очередь подпредставлений, он все равно захватит его. Я обнаружил, что 285 достаточно широки, чтобы не перекрывать индекс моего tableView.

person Community    schedule 17.09.2009
comment
Это не работает. Куда мне добавить метод? В .h или .m? Примечание: изменить на ...; int я = 0; if (i; i ‹[количество self.subviews]; i ++) { - person wagashi; 28.09.2011

Начиная с iOS 6, решение панели навигации не работало для меня из-за немного другого внешнего вида между UISearchBar и UINavigationBar. Итак, я переключился на что-то похожее на подход Падрейга, создав подкласс UISearchBar.

@interface SearchBarWithPad : UISearchBar
@end


@implementation SearchBarWithPad
- (void) layoutSubviews {

    [super layoutSubviews];
    NSInteger pad = 50;
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass: [UITextField class]])
        view.frame = CGRectMake (view.frame.origin.x, view.frame.origin.y, view.frame.size.width - pad, view.frame.size.height);
    }   
}
@end

Изменить: Ах, я не пробовал, но я думаю, что вы могли бы установить clipToBounds = YES на панели навигации, чтобы отключить новую тень, тем самым снова создав согласованный вид между двумя элементами управления.

person Ernie Thomason    schedule 04.09.2012
comment
Это не совсем работает с iOS 7 ... self.subviews теперь состоит из одного UIView, который, в свою очередь, содержит UITextField, который мы ищем. Итак, для iOS 7 вы можете сделать что-то вроде UIView * topView = [self.subviews objectAtIndex: 0]; затем выполните итерацию по topView.subviews, как указано выше, чтобы все заработало. - person Ernie Thomason; 19.07.2013

Я использую ViewDeck и хочу показать UISearchbar внутри leftController.

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

Я избавился от этого, написав UISearchBar, текстовое поле всегда будет иметь одинаковую ширину, но в одном случае есть перекрытие ViewDeck, а в другом случае я скрываю бит ViewDeck, а затем кнопка отмены займет место:

Создание подкласса UISearchBar

#import "ViewDeckSearchBar.h"
#define kViewDeckPadding 55

@interface ViewDeckSearchBar()
@property (readonly) UITextField *textField;
@end

@implementation ViewDeckSearchBar

static CGRect initialTextFieldFrame;

- (void) layoutSubviews {

    [super layoutSubviews];

    // Store the initial frame for the the text field
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        initialTextFieldFrame = self.textField.frame;
    });

    [self updateTextFieldFrame];
}

-(void)updateTextFieldFrame{

    int width = initialTextFieldFrame.size.width - (kViewDeckPadding + 6);
    CGRect newFrame = CGRectMake (self.textField.frame.origin.x,
                                  self.textField.frame.origin.y,
                                  width,
                                  self.textField.frame.size.height);

    self.textField.frame = newFrame;
}

-(UITextField *)textField{
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass: [UITextField class]]){
            return (UITextField *)view;
        }
    }

    return nil;
}

@end

ViewController класс

В моем классе навигации мне нужно перезаписать эти два UISearchbarDelegate метода, чтобы перейти в полноэкранный режим с результатами поиска:

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{

    [self.viewDeckController setLeftSize:0];

    // I am also using scopes, which works fine (they fade out when not searching)
    self.searchBar.scopeButtonTitles = @[@"Food",
                                         @"Beverages",
                                         @"Misc"];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
    self.viewDeckController.leftSize = 55;
}

Результат

ViewDeck показывает справа:

a
(источник: minus.com)

Искать в полноэкранном режиме (кнопка и кнопки осциллографа анимированы).

a
(источник: minus.com)

person Besi    schedule 29.01.2013
comment
Для iOS 7 и 8 вам необходимо изменить метод textField: - (UITextField *) textField {UIView * topView = [self.subviews objectAtIndex: 0]; для (UIView * вид в topView.subviews) {... - person Ricardo; 14.11.2014

searchBar.layoutMargins = UIEdgeInsetsMake(0, 0, 0, rightPad);

Мое старое решение по изменению фрейма UITextField перестало работать в iOS 13. Размещение UINavigationBar справа от UISearchBar никогда не помогало мне, поскольку они выглядели по-разному сверху и снизу.

person Ernie Thomason    schedule 22.09.2019
comment
Спасибо, это работает! Проверено на iOS 14. - person Paul Bénéteau; 08.06.2021

Извините, что снова все это перетащил.

Я хотел, чтобы UISearchBar был короче, и я использую UISearchBarController, но на самом деле не хочу индекс. Это потому, что справа у меня есть оверлей:

Длинная строка поиска

Для этого я подделываю sectionIndex с одним пустым элементом, а затем скрываю его. Вот как я это делаю:

 - (void)hideTableIndex {
    for (UIView *view in [tableView subviews]) {
        if ([view isKindOfClass:NSClassFromString(@"UITableViewIndex")]) {
            view.hidden = YES;
        }
    }
 }

 - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView {
    if (aTableView == self.searchDisplayController.searchResultsTableView) {
        return nil;
    } else {
        [self performSelector:@selector(hideTableIndex) withObject:nil afterDelay:0];
        return [NSArray arrayWithObjects:@"", nil];
    }
 }

 - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return 0;
 }

Это укорачивает UISearchBar и скрывает индекс, чтобы его нельзя было коснуться (в противном случае небольшая секция была бы расположена слева от наложения, которая при нажатии прокручивала бы UITableView вверх). Нравится:

alt text

Лучше всего то, что когда вы используете поиск, вы все равно получаете полосу полной ширины:

alt text

person Alastair Stuart    schedule 06.01.2011

Просто поместите UIView и поместите панель поиска внутри этого UIView. UIView должен иметь тот же размер, что и UISearchBar. это сработало для меня.

person Ideveloper    schedule 22.02.2011
comment
эй, как добавить панель поиска в UIView в текущем кадре? Я пробовал, но панель поиска находится за добавленным UIView .. спасибо! - person trillions; 28.02.2013

Текстовое поле, используемое в UISearchBar, является подклассом UITextField под названием UISearchBarTextField.

AFAIK, нет способа изменить размер UISearchBarTextField с помощью общедоступного API, а частный API не делает ' Я тоже многое могу сказать.

Может быть, вы можете взглянуть на подпредставления UISearchBarTextField, если они есть.

ОБНОВЛЕНИЕ: это не так.

ОБНОВЛЕНИЕ 2: я думаю, вам стоит взглянуть на свойство rightView UITextField. Приведенный ниже код, хотя он не работает, кажется хорошей отправной точкой:

UIView *emptyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[textField setRightView:emptyView];
[textField setRightViewMode:UITextFieldViewModeAlways];
[emptyView release];
person Can Berk Güder    schedule 17.02.2009
comment
Похоже, вы могли бы обмануть это, наклеив изображение поверх него. Добавьте строку: emptyView.backgroundColor = [UIColor blackColor]; в свой код, чтобы увидеть, как это будет работать. - person Padraig; 17.02.2009

Извините за некропостинг, но я нашел другой способ освободить немного места справа от текстового поля. У меня была проблема, что у меня было индексированное табличное представление с панелью поиска в качестве первой строки. Теперь индекс и панель поиска (сделанная в IB, кстати) перекрывались. Он перепробовал почти все, но безуспешно. Кажется, что свойства ширины и высоты текстового поля не отвечают ... Итак, я придумал следующее:

searchBar.showsCancelButton = YES;

UIView *cButton = [searchBar.subviews objectAtIndex:2];

cButton.hidden = YES;

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

person Community    schedule 08.08.2009
comment
Спасибо, это было легко и приятно. - person Chris Craft; 06.11.2009
comment
Вы можете добавить чек, что вы действительно получите UIButton сюда обратно. - person Besi; 29.01.2013

Каждый предоставил способы изменить пользовательский интерфейс. Я обнаружил, как получать идентичные результаты. Вы должны предоставить следующие две реализации:

  1. Используйте UISearchDisplayController Что еще более важно, убедитесь, что вы инициализировали его с помощью:

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController

Неспособность установить допустимый UISearchBar (или передача nil) предотвратит настройку UITextField для индекса.

  1. Вы должны вернуть допустимый массив заголовков, выполнив:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

Если вы вернете nil, индекс не будет отображаться, и UITextField не будет правильно настроен.

Я отправил отчет об ошибке в Apple, предполагая, что кажется логичным, что требуется только №2, а не №1. Я не нашел ничего в Руководстве по человеческому интерфейсу (iPhone HIG), требующего использования UISearchDisplayController.

person Mark    schedule 13.12.2009
comment
Я использовал контроллер отображения поиска IB, который, как мне кажется, реализует -initWithSearchBar:contentsController:, и это помогло изменить размер поля панели поиска. - person Alex Reynolds; 29.04.2010

Ключ состоит в том, чтобы использовать «Панель поиска и Контроллер отображения поиска», а не «Панель поиска» при использовании Interface Builder.

person Graeme Wicksted    schedule 20.05.2010

Это похоже на то, как будто Apple изменила размер представления (обратите внимание, что индекс анимирован справа, за пределами экрана), сделав его больше, чем экран.

Я предполагаю, что вам нужно будет реализовать метод searchBarTextDidBeginEditing: UISearchBarDelegate, чтобы вызвать это в соответствующий момент. Однако это кажется немного взломанным, может быть, есть способ лучше.

person Stephen Darlington    schedule 17.02.2009
comment
Спасибо, Стивен. Я заинтересован в том, чтобы исходное текстовое поле UISearchBar с самого начала было меньше. Есть и другие темы об индексной анимации, но сейчас я не пытаюсь разобраться с этим. - person Padraig; 17.02.2009

Еще одна попытка (хотя и утомительная) - изменить размер панели поиска и заполнить «пробел» панелью навигации. Работает на меня.

person Bart Jacobs    schedule 16.06.2009

То, что я придумал, не намного лучше. По сути, я создаю пустой вид с рамкой, которую хочу использовать для панели поиска. Затем я создаю UIToolbar, чтобы зайти за панель поиска. Обязательно установите его фрейм в тот же фрейм, что и UIView, за исключением, что значение Y должно быть -1; в противном случае вы получите две границы вверху. Затем создайте свой UISearchBar, но установите ширину фрейма на 30 (или что-то еще, что имеет смысл для вашего приложения) меньше, чем UIView. Добавьте их как subviews и установите свой UIView как tableHeaderView.

person Jeff Kelley    schedule 17.06.2009

Я последовал совету Майка, создав UIView, а затем поместил в него панель навигации и панель поиска UISearch. Проблема только в том, что первый раз, когда отображается панель поиска, ее фон такой же, как у панели навигации обычно?

Интересно, если я активирую поиск, то нажимаю отмену фона этого «исправленного» !?

Я использую SDK 3.0, поэтому я удалил элемент UISearchBar, созданный при перетаскивании UISearchDisplayController в свой NIB, затем создал представление, как описано выше, и подключил его к владельцу файла и выходу searchBar в контроллере отображения поиска.

person petert    schedule 23.11.2009

Работает нормально !!!

[searchBar setContentInset:UIEdgeInsetsMake(5, 0, 5, 35)];

person Oscar    schedule 05.05.2010
comment
Мне это нравится, потому что это не предполагает, что индекс объекта равен 0 или 2. Это означает, что мне не нужно специально тестировать это и менять каждое обновление SDK ... - person boymc; 14.02.2011
comment
Я думаю, что этот способ будет легким и приемлемым, но я думаю, что Apple должна исправить эту проблему, потому что, очевидно, следует отрегулировать положение строки заголовка левого индекса, если что-то было показано на экране просмотра таблицы. во всяком случае, я сейчас этим пользуюсь, спасибо за Оскар и все :) - person iXcoder; 02.04.2011
comment
ПРИМЕЧАНИЕ: UISearchBar не отвечает на setContentInset - person joshpaul; 22.09.2011
comment
Да ... Частный API вполне может привести к отклонению вашего приложения. - person jowie; 07.10.2011