ios - UISearchDisplayController 不完全覆盖 subview Controller

标签 ios iphone cocoa-touch ios7 uisearchdisplaycontroller

我有一个 Root View Controller ,它由顶部的搜索栏和底部的子 TableView Controller 组成。出于以下原因,我使用组合而不是将搜索栏分配给 TableView 的标题:

  1. 我不希望索引与搜索栏重叠(例如“通讯录”应用)。
  2. 我希望搜索栏具有粘性。也就是说,当我滚动表格 View 时它不会移动(再次像联系人应用程序)。
  3. 我的 TableView 已经有了标题。

因为搜索栏在 Root View Controller 中,所以我也在 Root View Controller 中实例化我的搜索显示 Controller 。我寻求建议的搜索 UI 有两个问题:

  1. 半透明的灰色覆盖层不会覆盖整个子 TableView 。它使标题的顶部和索引可见。
  2. 同样,搜索结果表不会覆盖整个子 TableView 。我知道如何手动更改此结果 TableView 的框架,但这样做只能修复......灰色半透明覆盖层的框架未链接到结果 TableView 框架。他们没有访问叠加层的属性。

1) 空闲

enter image description here

2) 输入搜索栏

enter image description here

3) 开始输入

enter image description here

#import "ContactsRootViewController.h"
#import "ContactsViewController.h"
#import "UIView+position.h"
#import "User.h"
#import "UserCellView.h"
#import "UserViewController.h"

@interface ContactsRootViewController ()

@property(nonatomic, strong) UISearchBar* searchBar;
@property(nonatomic, strong) ContactsViewController* contactsViewController;
@property(nonatomic, strong) UISearchDisplayController* searchController;
@property(nonatomic, strong) NSMutableArray* matchedUsers;

@end

@implementation ContactsRootViewController

#pragma mark UIViewController

- (NSString*)title
{
    return @"Contacts";
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.matchedUsers = [NSMutableArray array];

    self.searchBar = [[UISearchBar alloc] init];
    self.searchBar.placeholder = @"Search";
    [self.searchBar sizeToFit];
    [self.view addSubview:self.searchBar];
}

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

    if (self.contactsViewController == nil) {
        self.contactsViewController = [[ContactsViewController alloc] init];
        [self addChildViewController:self.contactsViewController];
        self.contactsViewController.view.frame = CGRectMake(
            0.0,
            self.searchBar.bottomY,
            self.view.frame.size.width,
            self.view.frame.size.height - self.searchBar.bottomY
        );
        self.contactsViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
        [self.view addSubview:self.contactsViewController.view];
        [self.contactsViewController didMoveToParentViewController:self];

        self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self.contactsViewController];
        self.searchController.delegate = self;
        self.searchController.searchResultsDataSource = self;
        self.searchController.searchResultsDelegate = self;
    }
}

#pragma mark UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.matchedUsers.count;
}

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* identifier = @"contactsRootViewUserCell";
    UserCellView* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[UserCellView alloc] initWithIdentifier:identifier];
    }
    cell.user = [self.matchedUsers objectAtIndex:indexPath.row];
    return cell;
}

#pragma mark UITableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self.navigationController pushViewController:[[UserViewController alloc] initWithUser:[self.matchedUsers objectAtIndex:indexPath.row]] animated:YES];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [UserCellView height];
}

#pragma mark UISearchDisplayControllerDelegate

- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self.matchedUsers removeAllObjects];

    searchString = [searchString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if (searchString.length > 0) {
        for (User* user in self.contactsViewController.allUsers) {
            NSRange match = [user.userDisplayName rangeOfString:searchString options:NSCaseInsensitiveSearch];
            if (match.location != NSNotFound) {
                [self.matchedUsers addObject:user];
            }
        }
    }

    return YES;
}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    [self.searchBar resignFirstResponder];
}

@end

最佳答案

我重新实现了 UISearchDisplayController,调用了我的实现 SearchController。它做同样的事情并具有类似的委托(delegate)回调,但搜索结果的框架可以由程序员控制。

标题

#import <Foundation/Foundation.h>

@class SearchController;

@protocol SearchControllerDelegate <NSObject>

@required
- (BOOL)searchController:(SearchController*)controller shouldReloadTableForSearchString:(NSString*)searchText;

@optional
- (void)searchController:(SearchController*)controller didShowSearchResultsTableView:(UITableView*)tableView;
- (void)searchController:(SearchController *)controller didHideSearchResultsTableView:(UITableView *)tableView;
- (void)searchControllerDidBeginSearch:(SearchController*)controller;
- (void)searchControllerDidEndSearch:(SearchController*)controller;

@end

@interface SearchController : UIViewController <UISearchBarDelegate>

@property(nonatomic, weak) NSObject<SearchControllerDelegate>* delegate;
@property(nonatomic, weak) NSObject<UITableViewDataSource>* searchResultsDataSource;
@property(nonatomic, weak) NSObject<UITableViewDelegate>* searchResultsDelegate;
@property(nonatomic, strong, readonly) UITableView* searchResultsTableView;

- (id)initWithSearchBar:(UISearchBar*)searchBar;

@end

实现

#import "SearchController.h"
#import "UIView+position.h"

@interface SearchController ()

@property(nonatomic, strong) UISearchBar* searchBar;
@property(nonatomic, strong) UIButton* searchResultsVeil;
@property(nonatomic, strong, readwrite) UITableView* searchResultsTableView;
@property(nonatomic, assign) BOOL searchResultsTableViewHidden;

- (void)didTapSearchResultsVeil;
- (void)hideSearchResults;

@end

@implementation SearchController

#pragma mark UIViewController

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

    [self.searchResultsTableView deselectRowAtIndexPath:[self.searchResultsTableView indexPathForSelectedRow] animated:YES];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.userInteractionEnabled = NO;
}

#pragma mark SearchController ()

- (void)hideSearchResults
{
    self.searchBar.text = nil;
    [self.searchResultsTableView reloadData];
    self.searchResultsTableViewHidden = YES;
    [self.searchBar resignFirstResponder];
}

- (void)didTapSearchResultsVeil
{
    [self hideSearchResults];
}

- (void)setSearchResultsTableViewHidden:(BOOL)searchResultsTableViewHidden
{
    if (self.searchResultsTableView != nil) {
        if (self.searchResultsTableView.hidden && !searchResultsTableViewHidden) {
            self.searchResultsTableView.hidden = searchResultsTableViewHidden;
            if ([self.delegate respondsToSelector:@selector(searchController:didShowSearchResultsTableView:)]) {
                [self.delegate searchController:self didShowSearchResultsTableView:self.searchResultsTableView];
            }
        } else if (!self.searchResultsTableView.hidden && searchResultsTableViewHidden) {
            self.searchResultsTableView.hidden = searchResultsTableViewHidden;
            if ([self.delegate respondsToSelector:@selector(searchController:didHideSearchResultsTableView:)]) {
                [self.delegate searchController:self didHideSearchResultsTableView:self.searchResultsTableView];
            }
        }
    }
}

- (BOOL)searchResultsTableViewHidden
{
    return self.searchResultsTableView == nil || self.searchResultsTableView.hidden;
}

#pragma mark SearchController

- (id)initWithSearchBar:(UISearchBar *)searchBar
{
    if (self = [super init]) {
        self.searchBar = searchBar;
        self.searchBar.delegate = self;
    }
    return self;
}

- (void)setSearchResultsDataSource:(NSObject<UITableViewDataSource> *)searchResultsDataSource
{
    _searchResultsDataSource = searchResultsDataSource;
    if (self.searchResultsTableView != nil) {
        self.searchResultsTableView.dataSource = searchResultsDataSource;
    }
}

- (void)setSearchResultsDelegate:(NSObject<UITableViewDelegate> *)searchResultsDelegate
{
    _searchResultsDelegate = searchResultsDelegate;
    if (self.searchResultsTableView != nil) {
        self.searchResultsTableView.delegate = searchResultsDelegate;
    }
}

#pragma mark UISearchBarDelegate

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if ([self.delegate searchController:self shouldReloadTableForSearchString:searchText]) {
        [self.searchResultsTableView reloadData];
        self.searchResultsTableViewHidden = [self.searchResultsTableView.dataSource tableView:self.searchResultsTableView numberOfRowsInSection:0] == 0;
    }
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    [searchBar setShowsCancelButton:YES animated:YES];
    if (self.searchResultsVeil == nil) {
        self.searchResultsVeil = [[UIButton alloc] initWithFrame:self.view.bounds];
        self.searchResultsVeil.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6];
        self.searchResultsVeil.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.searchResultsVeil addTarget:self action:@selector(didTapSearchResultsVeil) forControlEvents:UIControlEventTouchUpInside];

        self.searchResultsTableView = [[UITableView alloc] initWithFrame:self.searchResultsVeil.bounds style:UITableViewStylePlain];
        self.searchResultsTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        if ([self.searchResultsTableView respondsToSelector:@selector(setSeparatorInset:)]) {
            self.searchResultsTableView.separatorInset = UIEdgeInsetsMake(
                0.0,
                self.searchResultsTableView.width,
                0.0,
                0.0
            );
        }
        self.searchResultsTableViewHidden = YES;
        if (self.searchResultsDataSource != nil) {
            self.searchResultsTableView.dataSource = self.searchResultsDataSource;
        }
        if (self.searchResultsDelegate != nil) {
            self.searchResultsTableView.delegate = self.searchResultsDelegate;
        }

        [self.view addSubview:self.searchResultsVeil];
        [self.searchResultsVeil addSubview:self.searchResultsTableView];
    }
    self.view.userInteractionEnabled = YES;
    self.searchResultsVeil.hidden = NO;

    if ([self.delegate respondsToSelector:@selector(searchControllerDidBeginSearch:)]) {
        [self.delegate searchControllerDidBeginSearch:self];
    }
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
    [searchBar setShowsCancelButton:NO animated:YES];
    self.view.userInteractionEnabled = NO;
    self.searchResultsVeil.hidden = YES;

    if ([self.delegate respondsToSelector:@selector(searchControllerDidEndSearch:)]) {
        [self.delegate searchControllerDidEndSearch:self];
    }
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    [self hideSearchResults];
}

@end

用法

self.searchController = [[SearchController alloc] initWithSearchBar:self.searchBar];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self addChildViewController:self.searchController];
self.searchController.view.frame = CGRectMake(
    self.searchBar.x,
    self.searchBar.bottomY,
    self.searchBar.width,
    self.view.height - self.searchBar.bottomY
);
[self.view addSubview:self.searchController.view];
[self.searchController didMoveToParentViewController:self];

关于ios - UISearchDisplayController 不完全覆盖 subview Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21591093/

相关文章:

objective-c - 分组的 UITableView 在底部有 20px 的额外填充

ios - 如何在ios中TableviewCell中的uiTextField中实现日期

ios - Unity3d项目移植到IOS后可以编辑和添加代码吗?

ios - 转换 ARC 时出现 Lipo 错误

iphone - 使用 NSJSONSerializer iOS 发布 http JSON 请求

objective-c - AVAudioPlayer不断崩溃在这一行? (正在初始化)

iphone - 检查数据是否存在于 NSMutableArray 中的索引处

ios - 单击图像时如何在屏幕上随机移动 UIimageView

ios - 如何在 main.storyboard 中显示屏幕外的 UIView?

iphone - iOS:如何让两个 UIView 自动填充空间?