UISearchDisplayController с displaySearchBarInNavigationBar толкает представление результата вниз с помощью navigationBar.translucent = false

Я использую UISearchDisplayController, а новая функция ios 7 отображаетSearchBarInNavigationBar и непрозрачные панели навигации. Кажется, что контроллер отображения поиска неправильно позиционирует его.

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

with no text in search bar

with text in search bar

Ответы

Ответ 1

Только что разрешено "Под Opaque Bars" в раскадровке для вашего контроллера просмотра или если вам нравится код. Затем добавьте следующие строки. Ваш вкус:)

self.edgesForExtendedLayout = UIRectEdgeAll;
self.extendedLayoutIncludesOpaqueBars = YES;

Ответ 2

У меня была такая же проблема, и я исправил таким образом:

  • Подкласс UISearchDisplayController для UISearchBar в NavigationBar для iOS 6 и 7. Я перезаписал:
    -(void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        if (SYSTEM_VERSION_LESS_THAN(@"7")) {
            if(self.active == visible) return;

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

            if (visible) {
                [self.searchBar becomeFirstResponder];
            } else {
                [self.searchBar resignFirstResponder];
            }
        } else {
            self.searchContentsController.view.frame = CGRectMake(0, 0, kCurrentScreenWidth, kCurrentScreenHeight);
            [super setActive:visible animated:animated];
        }
    }

2. В UISearchDisplayDelegate я добавил следующее:

    - (void) searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
        // iOS7 Hack
        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) {
            controller.searchResultsTableView.contentInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f);
        }

    }

    - (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    {
        // -- iOS 7 Hack

        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) {
            controller.searchResultsTableView.frame = CGRectMake(0, 64, kCurrentScreenWidth, kCurrentScreenHeight-64);
            [controller.searchContentsController.view setNeedsLayout];
        }
    }

Ответ 3

У меня была такая же проблема, и после нескольких часов поиска ответа я решил посмотреть иерархию представлений. Кажется, что супервизор searchBar, который также является тусклым представлением, имеет y-начало 64 и высоту 504, что не заполняет весь экран. Не знаю, почему это так. Тем не менее, я закончил настройку y на 0 и высоту до высоты экрана. После этого, я вернул его обратно к исходному значению, иначе ваше представление таблицы содержимого будет искажено. Это не лучшее решение, но это лучше, чем ничего. Надеюсь, это поможет вам.

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    self.savedSearchTerm = nil;
    UIView *dimmedView = controller.searchBar.superview;
    CGRect frame = dimmedView.frame;
    frame.origin.y = 64;
    dimmedView.frame = frame;
    [self.tableView reloadData];
}

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    UIView *dimmedView = controller.searchBar.superview;
    CGRect frame = dimmedView.frame;
    frame.origin.y = 0;
    frame.size.height = 568;
    dimmedView.frame = frame;
}

Ответ 4

Я искал бесконечно онлайн для решения этой проблемы, но ничего, что было рекомендовано, работало в моем случае. Сброс кадра searchResultsTable не сработал, потому что он origin.y уже был в 0. Изменяя тип содержимого, который был обработан, но не фиксировал тусклое представление наложения и вызвало проблемы с просмотром прокрутки таблицы внизу (и баров). Я, наконец, получил лучший рабочий взлом, хотя он не совсем идеален, так как смены рамок обзора заметно заметны, но после этого по крайней мере позиционирование.

Используя Reveal.app, я смог вычислить иерархию представлений UISearchDisplayController, чтобы выяснить, что происходит, и это было результатом в моем случае:

UISearchDisplayControllerContainerView
    - UIView (0,0,320,504)
        - UISearchResultsTableView
    - UIView (0,20,320,44)
    - UIView (0,64,320,440)
        - _UISearchDisplayControllerDimmingView

Я делаю все программно, поэтому не уверен об обходном пути для NIB. Вот основные сведения о том, как мой UISearchBar и UISearchDisplayController настроены в моем методе viewDidLoad:

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
searchBar.delegate = self;
[searchBar sizeToFit];

self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self.searchDataSource;
self.searchController.searchResultsDelegate = self;
if ([self.searchController respondsToSelector:@selector(displaysSearchBarInNavigationBar)]) {
    self.searchController.displaysSearchBarInNavigationBar = YES;
}

И мой взлом, который работал в этом случае:

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

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fixSearchControllerPositionOnKeyboardAppear)
                                                     name:UIKeyboardWillShowNotification object:nil];

        if (self.searchController.isActive) {
            // the following is needed if you are return to this controller after dismissing the child controller displayed after selecting one of the search results
            [self performSelector:@selector(fixSearchControllerPositionForiOS7) withObject:nil afterDelay:0];
        }
    }
}

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

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}

- (void)fixSearchControllerPositionForiOS7 {
    UIView *view = self.searchController.searchResultsTableView.superview;
    // only perform hack if the searchResultsTableView has been added to the view hierarchy
    if (view) {

        // The searchDisplayController container view is already at 0,0, but the table view if shifted down 64px due to
        // bugs with the subviews in iOS 7, so shift the container back up by that negative offset.
        // This also fixes the position of the dimmed overlay view that appears before results are returned.
        CGFloat yOffset = 64.0;
        CGRect viewFrame = view.frame;
        if (CGRectGetMinY(viewFrame) == 0) {
            viewFrame.origin.y = -yOffset;
            viewFrame.size.height += yOffset;
            [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                view.frame = viewFrame;
            } completion:nil];
        }

        // we also need to adjust dimmed overlay view, so iterate through the search view controller container
        // view and make sure all subviews have their vertical origin set to 0
        UIView *searchContainerView = view.superview;
        for (NSInteger i = 0; i < [searchContainerView.subviews count]; i++) {
            UIView *subview = searchContainerView.subviews[i];
            if (CGRectGetMinY(subview.frame) > 0) {
                CGRect subviewFrame = subview.frame;
                CGFloat offset = CGRectGetMinY(subviewFrame);
                subviewFrame.origin.y = 0;

                if (offset == 20.0) {
                    // this subview is partially responsible for the table offset and overlays the top table rows, so set it height to 0
                    subviewFrame.size.height = 0;
                }
                else {
                    // this subview is the dimmed overlay view, so increase it height by it original origin.y so it fills the view
                    subviewFrame.size.height += offset;
                }
                subview.frame = subviewFrame;
            }
        }
    }
}

- (void)fixSearchControllerPositionOnKeyboardAppear {
    // call hack to reset position after a slight delay to avoid UISearchDisplayController from overriding our layout fixes
    [self performSelector:@selector(fixSearchControllerPositionForiOS7) withObject:nil afterDelay:0.1];
}

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        [self fixSearchControllerPositionForiOS7];
    }
}

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

Ответ 5

1.Use Reveal, найдите слой обложки и обнаружил, что _UISearchDisplayControllerDimmingView

2. Наденьте слой, измените соответствующий кадр, его можно найти на карте с помощью dimmingview с подлостью searchResultsTableView того же вида.

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
for(UIView * v in controller.searchResultsTableView.superview.subviews)
{
    if([v isKindOfClass:[NSClassFromString(@"_UISearchDisplayControllerDimmingView") class]])
    {
        v.frame = CGRectMake(0,20,320,400); // modify the frame
        NSLog(@"--------- %@",[v class]);
    }
}

3. Аналогично, если вам нужно настроить searchResultsTableView для фрейма, добавьте следующий код в

- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
    tableView.frame =CGRectMake(0, 20, 320, 480-64-44);
}