it-swarm.com.ru

Запрет UISearchDisplayController от скрытия панели навигации

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

64
hadronzoo

Новый класс UISearchController, представленный в iOS 8, имеет свойство hidesNavigationBarDuringPresentation, которое можно установить в false, если вы хотите, чтобы панель навигации была видимой (по умолчанию она все еще будет скрыта).

45
René

Я просто отладил немного в UISearchDisplayController и обнаружил, что он вызывает закрытый метод в UINavigationController, чтобы скрыть панель навигации. Это происходит в -setActive: animated :. Если вы создаете подкласс UISearchDisplayController и перезаписываете этот метод следующим кодом, вы можете предотвратить скрытие навигационной панели, подделав ее как скрытую.

- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
    if(self.active == visible) return;
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
    [super setActive:visible animated:animated];
    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    if (visible) {
        [self.searchBar becomeFirstResponder];
    } else {
        [self.searchBar resignFirstResponder];
    }   
}

Дайте мне знать, если это работает для вас. Я также надеюсь, что это не сломается в будущих версиях iOS ... Протестировано только на iOS 4.0.

60
stigi

Самое простое решение и никаких взломов. 

@interface MySearchDisplayController : UISearchDisplayController

@end

@implementation MySearchDisplayController

- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [super setActive: visible animated: animated];

    [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}

@end
52
Pavel Sharanda

Приведенные выше ответы не сработали для меня. Мое решение состоит в том, чтобы обмануть UISearchDisplayController, заставив его думать, что не было UINavigationController.

В вашем контроллере представления добавьте этот метод

- (UINavigationController *)navigationController {
    return nil;
}

Для меня это не имело неблагоприятных побочных эффектов, несмотря на то, что это выглядело как очень плохая идея ... Если вам нужно добраться до контроллера навигации, используйте [super navigationController].

28
joerick

Начиная с iOS 8.0, такого же поведения можно добиться, установив для свойства self.searchController.hidesNavigationBarDuringPresentationUISearchController значение false. 

Код в Swift выглядит так:

searchController.hidesNavigationBarDuringPresentation = false
10
Peter Ivanics

Пробовал это по-другому, без подкласса UISearchDisplayController. В вашем классе UIViewController, где вы устанавливаете делегат для UISearchDisplayController, реализуйте searchDisplayControllerDidBeginSearch: и добавьте использование 

[self.navigationController setNavigationBarHidden:NO animated:YES];

Сделал трюк для меня, надеюсь, что помогает.

9
ah335

Я столкнулся с этим, решая немного другую проблему. При использовании UISearchDisplayController я хочу, чтобы строка поиска была в панели навигации (не внизу).

Нетрудно поместить панель поиска в панель навигации (см. UISearchBar и UINavigationItem ). Однако UISearchDisplayController предполагает, что панель поиска всегда находится под панелью навигации и (как обсуждалось здесь) настаивает на том, чтобы при входе в поиск скрывать панель навигации, поэтому все выглядит ужасно. Кроме того, UISearchDisplayController окрашивает панель поиска светлее, чем обычно.

Я нашел решение. Хитрость заключается в том, чтобы (нелогично) отцепить UISearchDisplayController от управления любым UISearchBar вообще. При использовании xibs это означает удаление экземпляра панели поиска или, по крайней мере, отсоединение розетки. Затем создайте свой собственный UISearchBar:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
    [searchBar sizeToFit]; // standard size
    searchBar.delegate = self;

    // Add search bar to navigation bar
    self.navigationItem.titleView = searchBar;
}

Вам нужно будет вручную активировать контроллер отображения поиска, когда пользователь нажимает на панель поиска (в -searchBarShouldBeginEditing:), и вручную закрывать панель поиска, когда пользователь заканчивает поиск (в -searchDisplayControllerWillEndSearch:). 

#pragma mark <UISearchBarDelegate>

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // Manually activate search mode
    // Use animated=NO so we'll be able to immediately un-hide it again
    [self.searchDisplayController setActive:YES animated:NO];

    // Hand over control to UISearchDisplayController during the search
    searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;

    return YES;
}

#pragma mark <UISearchDisplayDelegate>

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
    // Un-hide the navigation bar that UISearchDisplayController hid
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
    UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;

    // Manually resign search mode
    [searchBar resignFirstResponder];

    // Take back control of the search bar
    searchBar.delegate = self;
}
4
jrc

iOS 7 немного портит ... для меня это сработало отлично:

/**
 *  Overwrite the `setActive:animated:` method to make sure the UINavigationBar 
 *  does not get hidden and the SearchBar does not add space for the statusbar height.
 *
 *  @param visible   `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
 *  @param animated  `YES` to use animation for a change in visible state, otherwise NO.
 */
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];

    [super setActive:visible animated:animated];

    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

Причина показать/скрыть статусбар 

3
Paul Peelen

Действительно хорошее решение, но оно ломало мое приложение под iOS6. Я должен был сделать следующую модификацию, чтобы заставить это работать.

@implementation ICSearchDisplayController

    - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        if (visible == YES) {
            [super setActive:visible animated:animated];
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        } else {
            [super setActive:NO animated:NO];
        }
    }
3
John Salerno

Это, кажется, решает это для меня. Протестировано в iOS5/6.1. Никаких визуальных проблем, которые я мог видеть.

- (void)viewDidAppear
{
    [super viewDidAppear];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)keyboardWillAppear:(NSNotification *)notification
{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

-(void)viewDidLayoutSubviews{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}
3
Daniel Ryan

Я думаю, что лучшее решение - это реализовать UISearchDisplayController самостоятельно.

Это не так сложно. Вам нужно только реализовать UISearchBarDelegate для вашего UIViewController и включить UITableView для отображения результатов поиска.

1
frankli

Я добавлял пользовательскую панель навигации на свой ViewController, который скрывался при поиске, быстрое, но не очень хорошее исправление 

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    [self.view addSubview:_navBar];
}

_navBar - это UINavigationBar, добавленный программно, Это помогло мне скрыть панель навигации.

0
sahiljain

Как указал jrc, «отцепить UISearchDisplayController от управления любым UISearchBar», похоже, работает для меня. Если я передаю nil в качестве параметра при создании UISearchDisplayController, панель навигации всегда остается видимой:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
0
Dasha Salo

@ Павел отлично работает. Однако я пытался вставить это в UIPopoverController, и текст в поле слегка выдвигается, когда текстовое поле панели поиска становится первым респондентом, и это выглядит немного уродливо, поэтому я исправил это, вызвав метод super с помощью animated установлена ​​в NO.

0
XCool

Просто хотел добавить к стиге ответ. Когда вы отменяете поиск и начинаете поиск снова - таблица результатов поиска не будет реагировать на прикосновения, поэтому вам нужно добавить следующую строку 

self.searchResultsTableView.alpha = 1;

Таким образом, обновленный код выглядит следующим образом

 - (void)setActive:(BOOL)visible animated:(BOOL)animated;
 {
    if(self.active == visible) return;
    if (visible) {
        [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
        [super setActive:visible animated:animated];
        [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        self.searchResultsTableView.alpha = 1;
        [self.searchBar becomeFirstResponder];
    } else {
        [super setActive:visible animated:animated];
        [self.searchBar resignFirstResponder];
    }
}
0
alex1704