【问题标题】:Changing the size of the UISearchBar TextField?更改 UISearchBar 文本字段的大小?
【发布时间】:2010-10-08 02:15:59
【问题描述】:

我有一个侧面有索引的 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)];

有什么想法吗?

【问题讨论】:

    标签: iphone search uitableview


    【解决方案1】:

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

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

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

    更新:它没有。

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

    UIView *emptyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
    [textField setRightView:emptyView];
    [textField setRightViewMode:UITextFieldViewModeAlways];
    [emptyView release];
    

    【讨论】:

    • 看起来你可以通过在上面贴一张图片来虚张声势。添加行:emptyView.backgroundColor = [UIColor blackColor];进入你的代码,看看它是如何工作的。
    【解决方案2】:

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

    我想你需要实现UISearchBarDelegatesearchBarTextDidBeginEditing: 方法才能在适当的时候触发它。但是,这确实有点 hacky,也许有更好的方法。

    【讨论】:

    • 谢谢斯蒂芬。我有兴趣让初始 UISearchBar 文本字段从一开始就变小。还有一些关于索引动画的其他线程,但这不是我现在想要解决的问题。
    【解决方案3】:

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

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

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

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

    感谢大家的建议。

    【讨论】:

    • 我使用 v3.0 iphone SDK 并将此代码放在 drawRect 中不起作用。实际上对我有用的是将此代码放在 layoutSubviews 中。不完全确定为什么 - 我能得出的唯一结论是 v2 -> v3 发生了变化
    【解决方案4】:

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

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

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

    【讨论】:

    • 非常感谢你!!!!我不知道如何让搜索栏设置动画。 layoutSubviews 是关键。
    • 我在 UINavigationBar 的右侧有一个 UISearchBar 并对其进出动画,就像 Safari 应用程序一样。 UISearchBar 的 layoutSubview 的这个技巧是让它像 Safari 一样工作的最后一块拼图。无需搜索子视图或类似的东西,这不是正确或干净的解决方案。再次感谢您的正确答案。
    • 这也以一种简单明了的方式为我解决了这个问题。谢谢!
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

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

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

        【讨论】:

        • 谢谢,这很简单。
        • 您可能需要添加一个检查,以确认您确实在此处获得了 UIButton
        【解决方案8】:

        正如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 的索引重叠。

        【讨论】:

        • 这不起作用。我应该在哪里添加方法?以 .h 还是 .m 为单位?注:改为...;诠释 i = 0; if (i ; i
        【解决方案9】:

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

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

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

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

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

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

        到处都是好书。

        【讨论】:

        • 工作得很好 - 一个补充 - 我们的表格视图应用了一些自定义样式并让导航栏和搜索栏看起来相同,我必须使父视图透明(即没有背景) - 所以如果事情不完全匹配试试这个。
        • 太棒了。只是纯粹的光彩。谢谢!
        【解决方案10】:

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

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

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

        【讨论】:

          【解决方案11】:

          每个人都提供了修改 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 的内容。

          【讨论】:

          • 我使用了 IB 搜索显示控制器——我认为它实现了-initWithSearchBar:contentsController:——这可以调整搜索栏字段的大小。
          【解决方案12】:

          很好用!!!

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

          【讨论】:

          • 我喜欢这个,因为它不是假设对象索引是 0 或 2。这意味着我不需要专门测试并更改每个 SDK 升级...
          • 我认为这种方式会很容易并且可以接受,但我认为Apple应该解决这个问题,因为很明显它应该调整左侧索引标题栏的位置,如果某些东西显示在表视图。无论如何,我现在使用这种方式,感谢奥斯卡和所有:)
          • 注意:UISearchBar 不回复setContentInset
          • 是的...私有 API 的东西很可能会导致您的应用被拒绝。
          【解决方案13】:

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

          【讨论】:

            【解决方案14】:

            很抱歉又把这一切拖了上来。

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

            最棒的是,当你使用搜索时,你仍然会得到全宽栏:

            【讨论】:

              【解决方案15】:

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

              【讨论】:

              • 嘿,如何将搜索栏添加到当前帧的 UIView 中?我试过了,但是搜索栏在那个添加的 UIView 后面。。谢谢!
              【解决方案16】:

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

              【讨论】:

              • 这在 iOS 7 中不太适用...... self.subviews 现在由一个 UIView 组成,而它又包含我们正在寻找的 UITextField。所以对于 iOS 7,你可以做类似 UIView *topView = [self.subviews objectAtIndex: 0];然后像上面一样遍历 topView.subviews 来完成这项工作。
              【解决方案17】:

              我正在使用ViewDeck 并希望在leftController 中显示一个 UISearchbar inside

              现在的问题是,如果我打开包含导航的左侧,右侧位与我的搜索字段重叠。

              我通过重写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
              

              ViewController 类

              在我的 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 显示在右侧:


              (来源:minus.com

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


              (来源:minus.com

              【讨论】:

              • 对于 iOS 7 和 8,您必须更改 textField 方法: -(UITextField *)textField{ UIView *topView = [self.subviews objectAtIndex: 0]; for (UIView *view in topView.subviews) {...
              【解决方案18】:
              searchBar.layoutMargins = UIEdgeInsetsMake(0, 0, 0, rightPad);
              

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

              【讨论】:

                猜你喜欢
                • 2013-03-06
                • 1970-01-01
                • 1970-01-01
                • 2012-12-21
                • 2018-10-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多