【问题标题】:UITextField within UISearchBar in iOS 7iOS 7 中 UISearchBar 中的 UITextField
【发布时间】:2013-10-01 05:39:58
【问题描述】:

我正在尝试使用其中的 TextField 实现与我的 UISearchBar 相同的外观,就像在我的 iOS 6 应用程序中一样。我尝试以多种方式对其进行编码,但尚未成功。问题是,自 iOS 7 以来,我无法以任何方式更改 TextField 的框架。结果是,我的 TextField 占据了 NavigationBar 中的所有空间并覆盖了右侧的 UIBarButtonItem(菜单按钮)。见下图:

iOS 6 代码: 这是我在 iOS 6 中的编码方式,我可以将 TextFields 框架设置为我喜欢的任何内容!

UITextField *sbTextField = (UITextField *)[searchBar.subviews lastObject];
[sbTextField removeFromSuperview];

CGRect rect = searchBar.frame;
rect.size.height = 32;
rect.size.width = 210;
sbTextField.frame = rect;

[sbTextField setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin];


UIBarButtonItem *searchBarNavigationItem = [[UIBarButtonItem alloc]  initWithCustomView:sbTextField];

[[self navigationItem] setLeftBarButtonItem:searchBarNavigationItem];

以上代码在 iOS 7 中的结果: ![iOS 7 外观]

iOS 7 代码: iOS 7 的不同之处在于,您需要使用 subViews 才能将 UITextField 添加到 UISearchBar/UINavigationBar。通过这样做,我还不能改变它的框架。它当前与右侧的 menuButton 重叠,可以在此代码下方的图片中看到...

UITextField* sbTextField;
CGRect rect = subView.frame;
rect.size.height = 32;
rect.size.width = 115;

for (UIView *subView in self.searchBar.subviews){
    for (UIView *ndLeveSubView in subView.subviews){

        if ([ndLeveSubView isKindOfClass:[UITextField class]])
        {

            sbTextField = (UITextField *)ndLeveSubView;
            sbTextField.backgroundColor =[UIColor whiteColor];
            UIBarButtonItem *searchBarNavigationItem = [[UIBarButtonItem alloc] initWithCustomView:sbTextField];
            sbTextField.frame = rect;
            self.navigationItem.leftBarButtonItem = searchBarNavigationItem;
            self.navigationItem.rightBarButtonItem =  menuButton;
            [sbTextField removeFromSuperview];

             break;
        }

    }

 }
 [self.searchBar reloadInputViews];

所以...是否可以以任何方式更改子视图的框架(TextField)? :(

编辑

答案有点蹩脚。为了使代码在 ios7 中使用 TextField 右侧的按钮,必须将 TextField 设置为 navigationBar 的 titleView。在 ios 6 中不是这种情况。但是会有其他故障,不建议在 iOS7 的 searchBars 中使用 TextField。请改用 searchDispalyController。请在下面查看我的答案

 self.navigationItem.titleView = sbTextField;

【问题讨论】:

  • 在下面查看我的答案 - 您的方法与 iOS 7 设计指南不一致,您正在重新发明轮子。 Apple 已经提供了一个在 UINavigationBar 中嵌入 UISearchBar 的小部件。一行代码。 stackoverflow.com/a/19185272/1103584

标签: ios uitextfield uinavigationbar ios7 uisearchbar


【解决方案1】:

您不应该在 iOS 7 中将 UITextField 放在 UINavigationBar 中,此小部件已由 Apple 提供。

在 iOS 7 中,您可以简单地使用 UISearchDisplayControllerUISearchBar,然后设置:

searchDisplayController.displaySearchBarInNavigationBar = YES

搜索栏将出现在您的 UINavigationBar 中,并且它可以与其他 UIBarButtonItems 配合使用,而无需您原来的 iOS 6 解决方案中的所有技巧和手动调整框架大小。

有一点需要注意 - 如果您要将其添加到仍支持早于 iOS 7 的操作系统的项目中,您需要确保检查调用,否则您的应用在运行时会崩溃旧操作系统。

if([searchDisplayController respondsToSelector:@selector(displaysSearchBarInNavigationBar)])
{
    searchDisplayController.displaysSearchBarInNavigationBar = YES;
}

请参阅 iOS 7 过渡指南的这一部分: https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/Bars.html

在 iOS 7 中,UISearchDisplayController 包括 显示SearchBarInNavigationBar 属性,您可以使用它来放置一个 导航栏中的搜索栏,类似于日历上的搜索栏 iPhone:

另一个注意事项 - 您应该考虑继续迁移到 AutoLayout,这样您就不必进行所有繁琐的框架操作。 Apple 推荐它,可能是有充分理由的(未来的设备会更大屏幕......?)

【讨论】:

  • 这是否向后兼容 ios6?
  • 没有。如果您想在支持旧操作系统的应用程序中使用它,则需要检查 displaySearchBarInNavigationBar = YES 调用,否则应用程序将崩溃。我会用详细信息更新我的答案。
【解决方案2】:

在 iOS 7 中,要访问文本字段,您必须在更多级别上重申。像这样更改您的代码

for (UIView *subView in self.searchBar.subviews){
    for (UIView *ndLeveSubView in subView.subviews){
    if ([ndLeveSubView isKindOfClass:[UITextField class]])
        {
            searchBarTextField = (UITextField *)ndLeveSubView;
            break;
        }
    }
   }

但清除 UISearchBar 的背景并在文本字段中设置搜索栏图标的最佳方法是:

[searchBar setBackgroundImage:[[UIImage alloc] init] ];//if you want to remove background of uisearchbar
UIImage *image = [UIImage imageNamed: @"search_icon.png"];
[searchBar setImage:image forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

【讨论】:

  • 感谢您的回复。该代码的工作方式与我的旧代码相同,但我无法在文本字段中重新定位搜索图标 + 文本或其大小:(
  • 创建带有所需框架的 UiImageView 并将其设置为 textField.leftView。
  • 如果我没有做错任何事,则无法正常工作。在 iOS 7 中获得一个您希望的简单文本字段似乎是一个诺贝尔价格......您将如何编码?你试过或者看到其他人在 ios7 中做过吗?
  • 好吧,我不明白这将如何解决我的问题。在 iOS 6 中设置 textField 的框架可以解决问题,但它不再听它了吗?我还尝试以编程方式在搜索栏左侧空间中添加 textField,在右侧空间中添加 menuButton。仍然 textField 只占用了搜索栏中的所有空间: self.navigationItem.leftBarButtonItem = searchBarNavigationItem; self.navigationItem.rightBarButtonItem = self.menuButton;
  • 能够在UISearchBar 中获取UITextField,但由于某种原因它使搜索栏无法使用。不显示我输入的任何内容。
【解决方案3】:

使用您的目标框架创建一个 UIView *textFieldContainer,将您的文本字段添加到该 UIView,然后将该 textFieldContainer 添加为导航项。即,您的方法保持不变,只是文本字段位于容器内,您可以使用该容器。

【讨论】:

  • 这是迄今为止最好和最简单的解决方案。谢谢!
【解决方案4】:

试试这个我不确定,但这应该可以工作,因为在 iOS 7 搜索栏有子视图,并且在该子视图中有两个子视图,其中一个是 UITextField

UIView *searchbarview = [searchBar.subviews objectAtIndex:0];
UITextField *sbTextField = (UITextField *)[searchbarview.subviews lastObject];
[sbTextField removeFromSuperview];

CGRect rect = searchBar.frame;
rect.size.height = 32;
rect.size.width = 210;
sbTextField.frame = rect;

[sbTextField setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin];


UIBarButtonItem *searchBarNavigationItem = [[UIBarButtonItem alloc] initWithCustomView:sbTextField];

[[self navigationItem] setLeftBarButtonItem:searchBarNavigationItem];

【讨论】:

    【解决方案5】:

    iOS6 & iOS7 兼容方案:

    - (void)setTextFieldAsDelegate:(UIView *)inputView {
        for (UIView *view in inputView.subviews) {
            if ([view isKindOfClass:[UITextField class]]) {
                searchBarTextField = (UITextField *)view;
                searchBarTextField.delegate = self;
                break;
            } else {
                [self setTextFieldAsDelegate:view];
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      快速解决方案

      for subView in searchBar.subviews{
              for deeperView in subView.subviews{
                  if let searchField:UITextField = deeperView as? UITextField{
                      searchField.layer.borderWidth = 1.0
                      searchField.layer.borderColor = UIColor(red: 134/255, green: 14/255, blue: 75/255, alpha: 1).CGColor
                      searchField.layer.cornerRadius = 5.0
                  }
              }
          }
      

      【讨论】:

        【解决方案7】:

        感谢 spotdog13。我终于设法通过以下方式使其适用于 iOS 7:

        #define TABLE_BOTTOM_MARGIN 5
        #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
        #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
        #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
        #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
        #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
        
        @interface HomeViewController ()
        
        @end
        
        @implementation HomeViewController
        
        @synthesize searchBar;
        @synthesize searchResults;
        
        - (void)viewDidLoad
        {
         if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        
        
            [searchBar sizeToFit]; // standard size
            searchBar.delegate = self;
        
            // Add search bar to navigation bar
            self.navigationItem.titleView = searchBar;
            }
        }
        
        - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
        // Manually activate search mode
        // Use animated=NO so we'll be able to immediately un-hide it again
        [self.searchDisplayController setActive:YES animated:NO];
        // Hand over control to UISearchDisplayController during the search
        // searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;
        
        return YES;
        }
        
        #pragma mark <UISearchDisplayDelegate>
        - (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
         // Un-hide the navigation bar that UISearchDisplayController hid
        [self.navigationController setNavigationBarHidden:NO animated:NO];
        }
        
        - (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
                                                   *)controller {
        searchBar = (UISearchBar *)self.navigationItem.titleView;
        // Manually resign search mode
        [searchBar resignFirstResponder];
        // Take back control of the search bar
        searchBar.delegate = self;
        }
        

        【讨论】:

        • 会有什么问题?在我看来,两种方式都可以接受。
        猜你喜欢
        • 2013-10-14
        • 1970-01-01
        • 2014-04-25
        • 2015-09-10
        • 1970-01-01
        • 2018-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多