锁定一个UISearchBar像游戏中心一个UITableView的顶部锁定一个UISearchBa

2019-05-13 08:47发布

有一个在UITableViews游戏中心,他们有在其顶部的搜索栏这个很酷的功能。 不像搜索条被放置在表头视图(因此它计数为标准表格单元格)的应用程序,相反,它似乎是用螺栓固定到它上面的父导航栏。 所以滚动表时,搜索栏确实动,但如果你滚动表格的边框上方,搜索栏从未停止触摸导航栏。

有谁知道这可能已经做了什么? 我在想,如果苹果可能放置在两个搜索栏和表父滚动视图,但我想知道,如果它可能比简单。

Answer 1:

鲍勃的回答是相反的:它应该是MIN(0,scrollView.contentOffset.y)。

另外,为了适当地支承调整(旋转时可能会出现的),另一个帧值应该被重复使用。

-(void)scrollViewDidScroll:(UIScrollView *)scrollView 
{
    UISearchBar *searchBar = searchDisplayController.searchBar;
    CGRect rect = searchBar.frame;
    rect.origin.y = MIN(0, scrollView.contentOffset.y);
    searchBar.frame = rect;
}


Answer 2:

你可以把搜索栏的表头和实施 - (无效)scrollViewDidScroll:为的tableView(UIScrollView的*)滚动视图的委托方法。 做这样的事情应该工作:

-(void) scrollViewDidScroll:(UIScrollView *)scrollView {
    searchBar.frame = CGRectMake(0,MAX(0,scrollView.contentOffset.y),320,44);
} 

如果您使用的searchDisplayController,你会使用self.searchDisplayController.searchbar访问搜索栏。



Answer 3:

在雨燕2.1和iOS 9.2.1

    let searchController = UISearchController(searchResultsController: nil)

        override func viewDidLoad() {
        /* Search controller parameters */
            searchController.searchResultsUpdater = self  // This protocol allows your class to be informed as text changes within the UISearchBar.
            searchController.dimsBackgroundDuringPresentation = false  // In this instance,using current view to show the results, so do not want to dim current view.
            definesPresentationContext = true   // ensure that the search bar does not remain on the screen if the user navigates to another view controller while the UISearchController is active.

            let tableHeaderView: UIView = UIView.init(frame: searchController.searchBar.frame)
            tableHeaderView.addSubview(searchController.searchBar)
            self.tableView.tableHeaderView = tableHeaderView

        }
        override func scrollViewDidScroll(scrollView: UIScrollView) {
           let searchBar:UISearchBar = searchController.searchBar
           var searchBarFrame:CGRect = searchBar.frame
           if searchController.active {
              searchBarFrame.origin.y = 10
           }
           else {
             searchBarFrame.origin.y = max(0, scrollView.contentOffset.y + scrollView.contentInset.top)

           }
           searchController.searchBar.frame = searchBarFrame
       }


Answer 4:

还有一个步骤,如果你想完全模仿游戏中心的搜索栏。

如果你开始friedenberg的出色答卷,以及在评论中提到的适用于iOS followben的修改6+,你仍然需要在搜索栏本身就是积极的调整功能。

在游戏中心,在搜索栏将在您向下滚动滚动表,但是当你尝试过表的边界向上滚动将保持固定的导航栏下方。 然而,当搜索栏是活动的并且搜索结果被显示,搜索栏不再与表滚动; 它保持固定在导航栏下方的地方

下面是实现该功能的完整代码(适用于iOS 6+)。 (如果你的目标的iOS 5或以下,你不需要包裹中的UISearchBar一个UIView)

CustomTableViewController.m

- (void)viewDidLoad
{
    UISearchBar *searchBar = [[UISearchBar alloc] init];
    ...
    UIView *tableHeaderView = [[UIView alloc] initWithFrame:searchBar.frame];
    [tableHeaderView addSubview:searchBar];

    [self.tableView setTableHeaderView:tableHeaderView];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    UISearchBar *searchBar = self.tableView.tableHeaderView.subviews.lastObject;
    CGRect searchBarFrame = searchBar.frame;

    /*
     * In your UISearchBarDelegate implementation, set a boolean flag when
     * searchBarTextDidBeginEditing (true) and searchBarTextDidEndEditing (false)
     * are called.
     */

    if (self.inSearchMode)
    {
        searchBarFrame.origin.y = scrollView.contentOffset.y;
    }
    else
    {
        searchBarFrame.origin.y = MIN(0, scrollView.contentOffset.y);
    }

    searchBar.frame = searchBarFrame;
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    self.inSearchMode = YES;
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
    self.inSearchMode = NO;
}

瞧! 现在,当搜索栏是无效的,将与移动表,并试图超越表边界时保持固定。 当激活时,它会保持固定的地方,就像在游戏中心。



Answer 5:

而其他的答案似乎乐于助人,部分做的工作,它并没有解决搜索栏的问题,不接受用户的触摸,因为它为你改变它的框架移动其父视图的范围之外。

更糟糕的是,当你在搜索栏上点击,使其成为第一个响应者,这是非常有可能的是,委托的tableView将调用tableView:didSelectRowAtIndexPath:对被搜索栏下的布局单元格。

为了解决上述这些问题,就需要包装的搜索栏在一个普通的UIView,一个视图,其能够处理的触摸的发生其边界之外。 通过这种方式,你可以中继那些接触到搜索栏。

因此,让我们做的第一:

class SearchBarView: UIView {
  override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
    for subview in subviews {
      if !subview.userInteractionEnabled { continue }

      let newPoint = subview.convertPoint(point, fromView: self)
      if CGRectContainsPoint(subview.bounds, newPoint) {
        return subview.hitTest(newPoint, withEvent: event)
      }
    }
    return super.hitTest(point, withEvent: event)
  }
}

现在,我们有一个名为UIView子类SearchBarView能够接收触摸发生的边界之外的。

其次,我们应该把搜索栏成新的视图,而视图控制器加载其视图:

class TableViewController: UITableViewController {
  private let searchBar = UISearchBar(frame: CGRectZero)
  ...

  override func viewDidLoad() {
    super.viewDidLoad()
    ...
    searchBar.sizeToFit()
    let searchBarView = SearchBarView(frame: searchBar.bounds)
    searchBarView.addSubview(searchBar)

    tableView.tableHeaderView = searchBarView
  }
}

最后,我们应该更新为用户向下滚动表视图,使其保持固定在顶部的搜索栏的框架:

override func scrollViewDidScroll(scrollView: UIScrollView) {
  searchBar.frame.origin.y = max(0, scrollView.contentOffset.y)
}

下面是结果:

-

重要提示:如果您的表视图有节,他们可能会影您的搜索栏,这样就需要把每个表视图的时候它们的顶部的搜索栏bounds得到更新。

viewDidLayoutSubviews是做到这一点的好地方:

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  ...
  if let tableHeaderView = tableView.tableHeaderView {
    tableView.bringSubviewToFront(tableHeaderView)
  }
}

-

希望这可以帮助。 您可以从下载示例项目在这里 。



Answer 6:

所有其他的答案在这里给我提供了有用的信息,但没有人使用的是iOS 7.1的工作。 下面是对我工作的简化版本:

MyViewController.h:

@interface MyViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchDisplayDelegate> {
}
@end

MyViewController.m:

@implementation MyViewController {

    UITableView *tableView;
    UISearchDisplayController *searchDisplayController;
    BOOL isSearching;
}

-(void)viewDidLoad {
    [super viewDidLoad];

    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    searchBar.delegate = self;

    searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    searchDisplayController.delegate = self;
    searchDisplayController.searchResultsDataSource = self;
    searchDisplayController.searchResultsDelegate = self;

    UIView *tableHeaderView = [[UIView alloc] initWithFrame:searchDisplayController.searchBar.frame];
    [tableHeaderView addSubview:searchDisplayController.searchBar];
    [tableView setTableHeaderView:tableHeaderView];

    isSearching = NO;
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {

    UISearchBar *searchBar = searchDisplayController.searchBar;
    CGRect searchBarFrame = searchBar.frame;

    if (isSearching) {
        searchBarFrame.origin.y = 0;
    } else {
        searchBarFrame.origin.y = MAX(0, scrollView.contentOffset.y + scrollView.contentInset.top);
    }

    searchDisplayController.searchBar.frame = searchBarFrame;
}

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    isSearching = YES;
}

-(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    isSearching = NO;
}

@end

注:如果您使用“下拉刷新”清单上,您就需要更换scrollView.contentInset.topscrollViewDidScroll:以恒定,让搜索栏在刷新动画滚动。



Answer 7:

如果您的部署目标是iOS的9或更高,那么你可以使用锚和设置的UISearchBar和编程的UITableView:

    private let tableView = UITableView(frame: .zero, style: .plain)
    private let searchBar = UISearchBar(frame: CGRect .zero)

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
        tableView.contentInset = UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)

        searchBar.delegate = self
        view.addSubview(tableView)
        view.addSubview(searchBar)
        NSLayoutConstraint.activate([
            searchBar.heightAnchor.constraint(equalToConstant: 44.0),
            searchBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            searchBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            searchBar.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
            ])
    }

我假设你从代码中创建的UISearchBar和UITableView的,而不是在故事板。



文章来源: Locking a UISearchBar to the top of a UITableView like Game Center