Изменение размера текстового поля UISearchBar? - PullRequest
30 голосов
/ 17 февраля 2009

У меня есть 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)];

Есть идеи?

Ответы [ 17 ]

30 голосов
/ 28 октября 2009

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

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

Очевидно, что в представлении таблицы может быть только 1 подпредставление в заголовке, поэтому сначала нужно поместить представление, затем N B и панель поиска.

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

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

Также они говорят о добавлении увеличительного стекла в верхнюю часть указателя.

Отличная книга вокруг.

16 голосов
/ 26 февраля 2009

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

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

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

8 голосов
/ 17 февраля 2009

Хорошо, я придумала решение.

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

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

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

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

6 голосов
/ 05 сентября 2012

Начиная с 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 на навигационной панели, чтобы отключить ее новую тень, создавая тем самым согласованный вид между двумя элементами управления.

6 голосов
/ 17 сентября 2009

Как указал Падрейг, все, что вам нужно сделать, это создать подкласс панели поиска. Создайте свой подкласс 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.

5 голосов
/ 29 января 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 http://i5.minus.com/jA34MnXVqPZez.png

Поиск в полноэкранном режиме (кнопки и кнопки области видимости анимированы).

a http://i2.minus.com/jjKEgXLur1kH6.png

2 голосов
/ 06 января 2011

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

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

Long search bar

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

 - (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

2 голосов
/ 22 февраля 2011

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

1 голос
/ 17 февраля 2009

Текстовое поле, используемое в 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];
1 голос
/ 13 декабря 2009

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...