30

我有一个 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)];

有任何想法吗?

4

18 回答 18

30

它比所有这些建议要容易得多。在界面生成器中,您可以放置​​一个视图,而不是将搜索栏作为表视图的标题。然后,在此视图中放置一个导航栏。抓住导航栏的左侧调整大小手柄并将其拉到右侧,直到 NB 仅 25 像素宽。清除 NB 中的 Title(双击选中,然后删除)。然后,将搜索栏添加到同一视图中。将其右侧调整大小手柄向左移动,调整使其紧靠 N B。就是这样。

如果需要,您也可以启用取消按钮,它也不会与索引重叠(保留在搜索栏中)。

显然,表格视图的标题中只能有 1 个子视图,这就是为什么您需要首先放置视图,然后是 NB 和搜索栏。

更新:请参阅从 Apress 开始 iPhone 开发,p。SDK 3 版本的 241。您只需在搜索时禁用索引。

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

他们还谈到在索引顶部添加放大镜。

到处都是好书。

于 2009-10-28T07:10:49.477 回答
16

为什么不将实际的 UISearchBar 水平缩小,并在其右侧放置一个(空的) UINavigationBar 呢?它们将呈现完全相同的背景。

比破解可能改变的 Apple 对象的内部结构要好。

此外,在对 UISearchBar 的宽度进行动画处理时,您会注意到内部文本字段并未随之进行动画处理。您可以通过在更改其帧后在动画块中调用 UISearchBar 的“layoutSubviews”来解决此问题。(这就是它确定内部文本字段大小的地方)

于 2009-02-26T03:08:49.460 回答
8

好的,我想出了一个解决方案。

  1. 创建 UISearchBar 的子类
  2. 将此代码包含在 drawRect: 方法中。

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

注意:kRightSideMargin 是我在头文件中设置的常量;我把它设置为25。

感谢其他人的建议。

于 2009-02-17T15:16:05.917 回答
6

正如Padraig 指出的那样,您所要做的就是将searchBar 子类化。创建您的 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 的索引重叠。

于 2009-09-17T01:50:33.640 回答
6

从 iOS 6 开始,导航栏解决方案对我来说效果不佳,因为现在 UISearchBar 和 UINavigationBar 之间的外观略有不同。因此,我通过继承 UISearchBar 切换到类似于 Padraig 的方法。

@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 来关闭它的新阴影,从而在两个控件之间再次创建一致的外观。

于 2012-09-04T20:15:26.120 回答
5

我正在使用ViewDeck希望.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

视图控制器类

在我的 Navigation 类中,我需要覆盖这两个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 显示在右侧:

一种
(来源:减号网

全屏搜索(按钮和范围按钮动画)。

一种
(来源:减号网

于 2013-01-29T14:38:50.600 回答
3
searchBar.layoutMargins = UIEdgeInsetsMake(0, 0, 0, rightPad);

我更改 UITextField 框架的旧解决方案在 iOS 13 中停止工作。将 UINavigationBar 放在 UISearchBar 的右侧对我来说效果不佳,因为它们在顶部和底部的外观不同。

于 2019-09-22T13:44:43.633 回答
2

很抱歉再次把这一切都拖了上来。

我希望 UISearchBar 更短,并且我正在使用 UISearchBarController,但实际上并不想要索引。这是因为我在右侧有一个叠加层:

长搜索栏

为此,我用一个空白项伪造了一个 sectionIndex,然后将其隐藏。我是这样做的:

 - (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 滚动到顶部)。像这样:

替代文字

最重要的是,当您使用搜索时,您仍然会得到全宽栏:

替代文字

于 2011-01-06T14:18:37.900 回答
2

只需放置一个 UIView 并将搜索栏放在该 UIView 中。UIView 必须与 UISearchBar 大小相同。这对我有用。

于 2011-02-22T12:13:47.760 回答
1

UISearchBar 中使用的文本字段是 UITextField 的子类,称为 UISearchBarTextField。

AFAIK,没有办法使用公共 API 调整 UISearchBarTextField 的大小,私有 API也没有透露太多信息。

如果有的话,也许你可以看看 UISearchBarTextField 的子视图。

更新:它没有。

更新 2:我认为你应该看看 UITextField 的 rightView 属性。下面的代码虽然不起作用,但似乎是一个很好的起点:

UIView *emptyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[textField setRightView:emptyView];
[textField setRightViewMode:UITextFieldViewModeAlways];
[emptyView release];
于 2009-02-17T14:03:42.547 回答
1

抱歉,Necroposting,但我找到了另一种在文本字段右侧留出一点空间的方法。我遇到了问题,我有一个带有搜索栏的索引表视图作为第一行。现在索引和搜索栏(在 IB 中制作,顺便说一句。)重叠了。它几乎尝试了所有方法,但都没有成功。似乎 textifield 的宽度和高度属性没有响应......所以我想出了这个:

searchBar.showsCancelButton = YES;

UIView *cButton = [searchBar.subviews objectAtIndex:2];

cButton.hidden = YES;

我仍然无法调整空间的大小,但现在可以这样做......虽然......很奇怪的解决方案......

于 2009-08-08T01:59:36.623 回答
1

每个人都提供了修改 UI 的方法。我发现了如何获得相同的结果。您必须提供以下两个实现:

  1. 使用 UISearchDisplayController 更重要的是,确保使用以下命令对其进行初始化:

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

未能设置有效的 UISearchBar(或传递 nil)将阻止为索引调整 UITextField。

  1. 您必须通过实现返回一个有效的标题数组:

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

如果返回 nil,则不会显示索引,并且 UITextField 将无法正确调整。

我已经向 Apple 提交了一份错误报告,表明只需要 #2 而不是 #1 似乎是合乎逻辑的。我在人机界面指南 (iPhone HIG) 中没有发现任何需要使用 UISearchDisplayController 的内容。

于 2009-12-13T09:39:54.977 回答
1

关键是在使用 Interface Builder 时使用“搜索栏和搜索显示控制器”而不是“搜索栏”。

于 2010-05-20T02:47:50.493 回答
0

它看起来好像 Apple 调整了视图的大小(请注意,索引在屏幕外向右移动),使其比屏幕大。

我想你需要实现的searchBarTextDidBeginEditing:方法UISearchBarDelegate来在适当的时候触发它。然而,这确实感觉有点hacky,也许有更好的方法。

于 2009-02-17T14:21:56.093 回答
0

另一种方法(虽然乏味)是调整搜索栏的大小并用导航栏填补“空白”。为我工作。

于 2009-06-16T18:34:06.537 回答
0

我想出的也好不了多少。基本上,我使用要用于搜索栏的框架创建一个空视图。然后我创建了一个 UIToolbar 放在搜索栏后面。一定要把它的frame设置成和UIView一样的frame,只是Y值必须是-1;否则,您将在顶部绘制两个边框。接下来创建您的 UISearchBar,但将框架的宽度设置为小于 UIView 的 30(或对您的应用有意义的任何值)。将它们添加为子视图并将您的 UIView 设置为 tableHeaderView。

于 2009-06-17T21:08:00.557 回答
0

我按照 Mike 的建议制作了一个 UIView,然后在其中放置了一个 Navigation Bar 和 UISearch Bar。唯一的问题是第一次显示搜索栏的背景通常与导航栏相同吗?

有趣的是,如果我激活搜索,然后点击取消这个'固定'的背景!?

我使用的是 SDK 3.0,所以我删除了当我将 UISearchDisplayController 拖入我的 NIB 时创建的 UISearchBar 项目,然后按上述方式制作视图并将其连接到文件所有者和搜索显示控制器中的 searchBar 出口。

于 2009-11-23T17:29:50.627 回答
0

它工作正常!

[searchBar setContentInset:UIEdgeInsetsMake(5, 0, 5, 35)];

于 2010-05-05T18:57:18.693 回答