UISearchbar TextField 的高度可以修改吗?

Can the height of the UISearchbar TextField be modified?

我正在测试我的 UI,我发现搜索栏对我来说有点太窄了。我还想确保视力较差或手部灵活性较差的人在调出他们想要的界面时没有问题。

所以,我想做的是调整UISearchbar里面的UITextfield的高度。

我尝试过的: 1. 在 Storyboard 中,添加 UISearchbar 高度限制 - 结果:搜索栏大小增加,但 UITextField 内部保持不变。

  1. 访问UISearchbar里面的UITextField并修改它的高度 - 结果:控制台输出显示参数被修改,但是在屏幕上,UITextField高度保持不变。

注意 - 我可以使用方法 2 修改 UITextField 的其他参数,并且更改会反映在屏幕上,所以我知道我正在进入 UITextField

方法2的代码,放在ViewController的viewDidLoad()里面UISearchbar所在的地方:

for tempView in (self.roomInfoSearchBar.subviews[0] as! UIView).subviews as! [UIView]
{
  if let tV = tempView as? UITextField
  {
    var currentFrameRect = tV.frame
    currentFrameRect.size.height = 80
    //tV.layer.backgroundColor = UIColor.blueColor().CGColor  //This works fine
    //tV.layer.cornerRadius = 5  //This works fine
    //tV.font = UIFont(name: "Courier", size: 40)  //This works fine
    println(tV.frame.height)  //console output:0.0
    tV.frame = currentFrameRect
    println(tV.frame) //console output:(0.0, 0.0, 0.0, 80.0)
    println(currentFrameRect) //console output:(0.0, 0.0, 0.0, 80.0) - redundant, just checking
    println(tV.frame.height) //console output:80.0 - it says 80, but screen shows searchbar definitely not 80.
  }
}

我认为这与自动布局有关,无论参数设置在何处,它都能以某种方式忽略参数。我想继续使用自动布局,因为它为我做了很多工作,但我希望它能像在 Storyboard 中那样工作,当用户设置设置时,它会在其自动布局中使用这些参数,并在可以时抱怨' t 而不是在没有反馈的情况下忽略设置。

编辑:

回应马赫什。我知道的不多objective C++,但我尽力把你写的转换成swift。这是我的:

(在我的 viewcontroller.swift 里面)

func viewDIdLayoutSubviews()
{
  super.viewDidLayoutSubviews()
  self.roomInfoSearchBar.layoutSubviews()

  var topPadding: Float = 5.0
  for view in (self.roomInfoSearchBar.subviews[0] as! UIView).subviews as! [UIView]
  {
    if let tfView = view as? UITextField
    {
      var calcheight = self.roomInfoSearchBar.frame.size.height - 10
      tfView.frame = CGRectMake(tfView.frame.origin.x, CGFloat(topPadding), tfView.frame.size.width, self.roomInfoSearchBar.frame.size.height - CGFloat(topPadding * 2))
    }
  }
}

我保留了用于访问文本字段的代码,因为我在将您的代码转换为 swift 时遇到了一些问题。对于 CGRectMake - swift 抱怨各种类型,包括 topPadding 不是 CGFloat,对于最后一个变量(Y 大小),它再次不喜欢将 CGFloat 与 Float 混合,所以我也不得不改变它。

不幸的是,它似乎不起作用。我在情节提要中将 UISearchbar 高度更改为 80,我得到了一个非常高的搜索栏,文本字段覆盖了总高度的大约 1/3。

编辑 #2:合并 Yuyutsu 和 Mahesh 代码的更正版本。 仍然不完美,但更接近。 Yuyutsu 的代码有效,但正如我的评论中所述,该字段不居中,首次加载视图时调整大小也可见(从高度 A 跳到高度 B)。另一个缺陷是,因为调整大小是在 viewDidAppear 一旦方向改变,字段 returns 到固有大小。

我的代码基于 Yuyutsu 的:

  override func viewDidAppear(animated: Bool)
  {
    super.viewDidAppear(animated)
    var roomInfoSearchBarFrame = roomInfoSearchBar.frame
    var newHeight: CGFloat = 60
    for subView in roomInfoSearchBar.subviews
    {
      for subsubView in subView.subviews
      {
        if let textField = subsubView as? UITextField
        {
          var currentTextFieldFrame = textField.frame
          var recenteredY = (roomInfoSearchBarFrame.height - newHeight)/2
          var newTextFieldFrame = CGRectMake(textField.frame.minX, recenteredY, textField.frame.width, newHeight)

          textField.frame = newTextFieldFrame
          textField.borderStyle = UITextBorderStyle.RoundedRect
          textField.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
          //textField.backgroundColor = UIColor.redColor()
          //                    textField.font = UIFont.systemFontOfSize(20)
        }
      }
    }
  }

查看 Yuyutsu 的代码,我想知道我还可以将此调整放在哪里,我通过另一个 Whosebug post 遇到了 link。根据我阅读的内容,我发现 Mahesh 的回答应该有效。这是我意识到为什么它不起作用的地方 - 我需要 覆盖 func viewWillLayoutSubviews().

当前代码:随着方向的改变保持大小。但是size jump还是可见的(应该是不可见的)

  override func viewWillLayoutSubviews()
  {
    super.viewWillLayoutSubviews()
    var roomInfoSearchBarFrame = roomInfoSearchBar.frame
    var newHeight: CGFloat = 60
    for subView in roomInfoSearchBar.subviews
    {
      for subsubView in subView.subviews
      {
        if let textField = subsubView as? UITextField
        {
          var currentTextFieldFrame = textField.frame
          var recenteredY = (roomInfoSearchBarFrame.height - newHeight)/2
          var newTextFieldFrame = CGRectMake(textField.frame.minX, recenteredY, textField.frame.width, newHeight)

          textField.frame = newTextFieldFrame
          textField.borderStyle = UITextBorderStyle.RoundedRect
          textField.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
          //textField.backgroundColor = UIColor.redColor()
          //                    textField.font = UIFont.systemFontOfSize(20)
        }
      }
    }
  }

所以现在,唯一剩下的就是尝试让文本字段在视图可见之前设置大小,这样就不会出现用户可见的大小偏移。

最终编辑:完全可用的代码 在 Yuyutsu 的额外帮助下,下面的代码可以完成我想要的一切 - 从设定大小开始,字段居中,处理旋转。

  override func viewDidLayoutSubviews()
  {
    super.viewDidLayoutSubviews()
    self.roomInfoSearchBar.layoutIfNeeded()
    self.roomInfoSearchBar.layoutSubviews()

    var roomInfoSearchBarFrame = roomInfoSearchBar.frame
    var newHeight: CGFloat = 60 //desired textField Height.
    for subView in roomInfoSearchBar.subviews
    {
      for subsubView in subView.subviews
      {
        if let textField = subsubView as? UITextField
        {
          var currentTextFieldBounds = textField.bounds
          currentTextFieldBounds.size.height = newHeight
          textField.bounds = currentTextFieldBounds
          textField.borderStyle = UITextBorderStyle.RoundedRect
          //textField.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
        }
      }
    }
  }

谢谢悠悠。 感谢 Mahesh 从一开始就提出了最终的解决方案,只是遗漏了一些关键部分。

您可以更改内部文本字段的高度,试试这个代码。

步骤 1) 设置约束以增加 UISearchBar 高度,然后设置搜索栏出口并在视图控制器中写下此代码。

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    [self.searchBar layoutSubviews];

    float topPadding = 5.0;
    for(UIView *view in self.searchBar.subviews)
    {
        for(UITextField *textfield in view.subviews)
        {
            if ([textfield isKindOfClass:[UITextField class]]) {
                textfield.frame = CGRectMake(textfield.frame.origin.x, topPadding, textfield.frame.size.width, (self.searchBar.frame.size.height - (topPadding * 2)));
            }
        }
    }
}

此外,如果您想更改搜索栏中的任何其他内容,那么您可以找到确切的基本元素,例如 UILabelUIImageUIView inside UITextField subviews 并且可以更改 frame还有 imageother properties。谢谢

编辑:

正如您在 swift 中所问,我正在将其写在 swift 中。我认为你在尝试做错事。请试试这个。

func viewDIdLayoutSubviews()
{
    super.viewDidLayoutSubviews()
    self.roomInfoSearchBar.layoutSubviews()

    var topPadding: Float = 5.0
    for view in self.roomInfoSearchBar.subviews as [UIView] 
    {
        for viewNew in view.subviews as [UIView] 
        {
            if viewNew.isKindOfClass(UITextField) 
            {
                viewNew.frame = CGRectMake(viewNew.frame.origin.x, CGFloat(topPadding), viewNew.frame.size.width, self.roomInfoSearchBar.frame.size.height - CGFloat(topPadding * 2))
            }
        }
    }
}

您将 0 索引视图作为要循环的第一个和最后一个视图。我认为这就是您翻译的代码不起作用的问题。尝试一次,请回复。

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        for subView in searchBars.subviews  {
            for subsubView in subView.subviews  {
                if let textField = subsubView as? UITextField {
                     var bounds: CGRect
                bounds = textField.frame
                bounds.size.height = 35 //(set height whatever you want)
                    textField.bounds = bounds
                    textField.borderStyle = UITextBorderStyle.RoundedRect
//                    textField.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
                    textField.backgroundColor = UIColor.redColor()
//                    textField.font = UIFont.systemFontOfSize(20)
                }
            }
        }

    }

这可能对你有帮助:)

我发现接受的答案有时有问题。
这就是我如何解决为 searchBar 设置自定义高度的问题:我已经设置了我想要的大小的彩色图像并将其添加到 viewDidLoad:

中的 searchBar 的文本字段
let image = getImageWithColor(UIColor.whiteColor(), size: CGSizeMake(600, 60))
searchBar.setSearchFieldBackgroundImage(image, forState: .Normal)

紧接着这个函数取自 here

func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
    var rect = CGRectMake(0, 0, size.width, size.height)
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIRectFill(rect)
    var image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

如果您使用:

func setSearchFieldBackgroundImage(backgroundImage: UIImage?, forState state: UIControlState)   

UISearchBar 的 UITextfield 的高度将与 Image 的高度相同。

您可以放入一个图片,用它来自定义UISearchBar 的UITextfield 高度和背景图片。

或者您可以使用下面的函数创建圆角 UIImage:

func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
    let rect = CGRectMake(0, 0, size.width, size.height)
    let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0)
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    path.fill()
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

UIImage的宽度ignored.But有一个圆角半径,最好大于10.0

代码如下所示:

let image = self.getImageWithColor(UIColor.lightGrayColor(), size: CGSizeMake(20, 20))
searchBar.setSearchFieldBackgroundImage(image, forState: .Normal)

这是正确的 Swift 4.0 关于如何更改 UISearchBar 高度的答案:

  let image = getImageWithColor(color: UIColor.clear, size: CGSize(width: 1, height: 40))
  searchBar.setSearchFieldBackgroundImage(image, for: .normal)

使用以下方法:

  func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

4 日测试。六月。 2018

Swift4.2/iOS12.1 的更新:

let newHeight : CGFloat = 45
for subview in searchBar.subviews {
    for subsubview in subview.subviews {
        if let textField = subsubview as? UITextField {
            var currentTextfieldBounds = textField.bounds
            currentTextfieldBounds.size.height = newHeight
            textField.bounds = currentTextfieldBounds
            textField.borderStyle = .roundedRect
            textField.contentVerticalAlignment = .center
        }
    }
}

对于 swift 5.0,效果很好:

extension UIImage {
    class func image(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { rendererContext in
            color.setFill()
            rendererContext.fill(CGRect(origin: .zero, size: size))
        }
    }
}

extension UISearchBar {
    func customize() {
        setSearchFieldBackgroundImage(UIImage.image(color: .clear, size: CGSize(width: 1, height: 44)), for: .normal)

        // other settings
        searchBarStyle = .minimal
        searchTextPositionAdjustment = UIOffset(horizontal: 0, vertical: 0)
        tintColor = .black
        backgroundColor = .whiteBackground
        searchTextField.leftViewMode = .never
        searchTextField.textColor = .black
        searchTextField.backgroundColor = UIColor.lightGrayBackground
        searchTextField.layer.borderColor = UIColor.gray.cgColor
        searchTextField.cornerRadius = 22
        searchTextField.borderWidth = 0.5
    }
}

只需使用:

let searchBar = UISearchBar()
searchBar.customize()

基于 这是 Swift 5.* 的代码:

extension UISearchBar {
    func updateHeight(height: CGFloat, radius: CGFloat = 8.0) {
        let image: UIImage? = UIImage.imageWithColor(color: UIColor.clear, size: CGSize(width: 1, height: height))
        setSearchFieldBackgroundImage(image, for: .normal)
        for subview in self.subviews {
            for subSubViews in subview.subviews {
                if #available(iOS 13.0, *) {
                    for child in subSubViews.subviews {
                        if let textField = child as? UISearchTextField {
                            textField.layer.cornerRadius = radius
                            textField.clipsToBounds = true
                        }
                    }
                    continue
                }
                if let textField = subSubViews as? UITextField {
                    textField.layer.cornerRadius = radius
                    textField.clipsToBounds = true
                }
            }
        }
    }
}

private extension UIImage {
    static func imageWithColor(color: UIColor, size: CGSize) -> UIImage? {
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(rect)
        guard let image: UIImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        return image
    }
}

下面是我们如何应用它:

searchBar?.setSearchTextField(height: 48)

结果如下:

答案的 MonoTouch 版本:

UIImage GetImageWithColor(UIColor color, CGSize size)
{
    var rect = new CGRect(0, 0, size.Width, size.Height);
    var path = UIBezierPath.FromRoundedRect(rect, 5);
    UIGraphics.BeginImageContextWithOptions(size, false, 0);
    color.SetFill();
    path.Fill();
    var image = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return image;
}

var image = GetImageWithColor(UIColor.LightGray, new CGSize(20, 20));
searchBar.SetSearchFieldBackgroundImage(image, UIControlState.Normal);