如何左对齐UISearchBar的占位文本

13

这是设计师要我创建的搜索栏

我需要创建一个像这样的自定义搜索栏。我的问题在于左对齐占位符文本,以及将搜索图标放在右侧。我有一个搜索图标的png文件,我已经尝试将其用作UIImageView,并将该UIImageView设置为UISearchBarUITextFieldrightView。但是这个解决方案没有起作用,我想不出更好的方法了。请问有人有解决方案吗?


不确定文本的对齐方式,但您可以考虑将搜索图标制作为自定义 UIButton,放置在搜索栏的顶部,并作为“输入”按钮工作。我遇到过一些这样做的应用程序,我总是很喜欢有不必点击搜索字段、打开键盘并从那里点击“搜索”重新运行搜索的选项。 - Nerrolken
我已经在另一个问题中回答过这个问题。很高兴收到有关如何改进它的反馈:https://dev59.com/63jZa4cB1Zd3GeqPclOb#25827025 - bdv
10个回答

12

如果需要进行这些自定义操作,请不要使用 UISearchBar。您需要使用UITextFieldUIImageView创建自己的搜索栏,并响应委托调用。


但请注意,UISearchController似乎需要使用实际的UISearchBar或其子类。 - Pierre Houston
2
但是我想要搜索栏的所有其他内置功能(例如取消和 x 按钮)- 我只想将占位符文本左对齐 - 这是否太过分了?而且为什么做起来那么难呢? - jbyrd

2

根据Mohittomar的回答,@DevC要求在占位符末尾添加空格,在这里提供Swift代码:

我在UISearchBar中子类化了占位符,在设置值后,检查最后一个字符是否为空格。然后获取一个空格的大小以及需要添加到左侧对齐的空格数量。

class SearchBar: UISearchBar, UISearchBarDelegate {
override var placeholder:String? {
    didSet {
        if let text = placeholder {
            if text.last != " " {

// get the font attribute
                let attr = UITextField.s_appearanceWhenContainedIn(SearchBar).defaultTextAttributes
// define a max size
                let maxSize = CGSizeMake(UIScreen.mainScreen().bounds.size.width - 60, 40)
// get the size of the text
                var widthText = text.boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
// get the size of one space
                var widthSpace = " ".boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
                let spaces = floor((maxSize.width - widthText) / widthSpace)
// add the spaces
                let newText = text + (" " * spaces)
// apply the new text if nescessary
                if newText != text {
                    placeholder = newText
                }
            }
        }
    }
}

2
Drix的答案提供了一个可行的解决方案。
import Foundation
import UIKit

class LeftAlignedSearchBar: UISearchBar, UISearchBarDelegate {
    override var placeholder:String? {
        didSet {
            if #available(iOS 9.0, *) {
                if let text = placeholder {
                    if text.characters.last! != " " {
                        // get the font attribute
                        let attr = UITextField.appearanceWhenContainedInInstancesOfClasses([LeftAlignedSearchBar.self]).defaultTextAttributes
                        // define a max size
                        let maxSize = CGSizeMake(UIScreen.mainScreen().bounds.size.width - 87, 40)
//                        let maxSize = CGSizeMake(self.bounds.size.width - 92, 40)
                        // get the size of the text
                        let widthText = text.boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
                        // get the size of one space
                        let widthSpace = " ".boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
                        let spaces = floor((maxSize.width - widthText) / widthSpace)
                        // add the spaces
                        let newText = text + ((Array(count: Int(spaces), repeatedValue: " ").joinWithSeparator("")))
                        // apply the new text if nescessary
                        if newText != text {
                            placeholder = newText
                        }
                    }
                }
            }
        }
    }
}

在iOS 8中,方法appearanceWhenContainedInInstancesOfClasses不可用,但是有一个解决方法可以在iOS 8中使用,在这里


2

以下是Drix答案的可行的Swift 3解决方案:

import Foundation
    import UIKit

    class LeftAlignedSearchBar: UISearchBar, UISearchBarDelegate {
        override var placeholder:String? {
            didSet {
                if #available(iOS 9.0, *) {

                    if let text = placeholder {
                        if text.characters.last! != " " {
                            // get the font attribute
                            let attr = UITextField.appearance(whenContainedInInstancesOf: [LeftAlignedSearchBar.self]).defaultTextAttributes
                            // define a max size
                            let maxSize = CGSize(width: UIScreen.main.bounds.size.width - 87, height: 40)
                            // let maxSize = CGSize(width:self.bounds.size.width - 92,height: 40)
                            // get the size of the text
                            let widthText = text.boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:attr, context:nil).size.width
                            // get the size of one space
                            let widthSpace = " ".boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:attr, context:nil).size.width
                            let spaces = floor((maxSize.width - widthText) / widthSpace)
                            // add the spaces
                            let newText = text + ((Array(repeating: " ", count: Int(spaces)).joined(separator: "")))
                            // apply the new text if nescessary
                            if newText != text {
                                placeholder = newText
                            }
                        }
                    }
                }
            }
        }

        /*
        // Only override draw() if you perform custom drawing.
        // An empty implementation adversely affects performance during animation.
        override func draw(_ rect: CGRect) {
            // Drawing code
        }
        */

    }

2

SWIFT 3

Swift 3不允许覆盖占位符属性。以下是Drix答案的修改版本。

func setPlaceHolder(placeholder: String)-> String
   {

       var text = placeholder
           if text.characters.last! != " " {

               //                         define a max size

               let maxSize = CGSize(width: UIScreen.main.bounds.size.width - 97, height: 40)

               //                        let maxSize = CGSizeMake(self.bounds.size.width - 92, 40)
               // get the size of the text
               let widthText = text.boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:nil, context:nil).size.width
               // get the size of one space
               let widthSpace = " ".boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:nil, context:nil).size.width
               let spaces = floor((maxSize.width - widthText) / widthSpace)
               // add the spaces
               let newText = text + ((Array(repeating: " ", count: Int(spaces)).joined(separator: "")))
               // apply the new text if nescessary
               if newText != text {
                   return newText
               }

           }

       return placeholder;
   }

然后调用该函数:

searchBar.placeholder = self.setPlaceHolder(placeholder: "your placeholder text");

我的搜索栏图标在键盘弹出2-3次后就跑到了搜索栏外面。 - guru

0

如果您想让控件按照您的意愿进行响应,那么您可能需要创建自己的自定义控件。

该控件可以分为三个部分:

  1. 一个背景UIImageView
  2. 一个UITextField
  3. 一个UIButton,如果您希望用户与之交互,则用于搜索图标

最简单的方法可能是创建一个新类MySearchBar,并在私有接口中包含这三个部分:

@interface MySearchBar ()
@property (nonatomic, strong) UISearchBar* searchBar;
@property (nonatomic, strong) UITextField* textField;
@property (nonatomic, strong) UIButton* button;
@end

在你的MySearchBar中,你可以创建自己的组件,自定义它,使其外观更好。为了获取搜索结果,你的控件可以有一个委托id<UISearchBarDelegate>(你的UIViewController),它将基本上模拟具有标准UISearchBar的情况。
剩下的就是在你的控制器中创建你的MySearchBar并将委托设置为你的视图控制器。来自UISearchBarDelegate的消息可以直接发送到你的UIViewController,也可以先经过MySearchBar进行过滤或预处理。

感谢您详细的回答,我一定会使用它。 - Chandler De Angelis

0

可以从故事板完成,搜索栏的属性检查器上有名为“语义”的组合框,如果将其设置为强制从右到左,则可以实现右对齐的搜索栏,并且它还具有类似的功能,可以从左侧对齐。


0

不需要任何定制,只需这样做...

    searchBar.placeholder=@"Search                                                        ";

搜索栏具有中央文本对齐功能,因此只需提供一些大文本即可。如果您的文本很小,则在占位符文本后使用一些空格即可。

3
如果有人对任何回答进行了负评,首先请提交一个正确的答案。 - Mohit Tomar
1
只有在动态检查所需空格数量并添加时,此方法才能完美运行。
  • 覆盖占位符变量,并根据控制器的大小、文本的大小以及一个空格的大小再次检查文本的大小。 如果有人想让我发布代码,请告诉我。
- Adriano Spadoni
1
嘿@DevC,我会回答以便能够发布代码,现在就可以了。 - Adriano Spadoni
iOS 8 将修剪占位符周围的空白。 - jbyrd

0

Xamarin 版本

SearchBar.MovePlaceHolderLeft();

public static void MovePlaceHolderLeft(this UISearchBar  searchbar)
{
    NSAttributedString text = new NSAttributedString(searchbar.Placeholder ?? "");
    // define a max size
    var maxSize = new CGSize(width: UIScreen.MainScreen.Bounds.Size.Width - 97, height: 40);
    // get the size of the text
    var widthText = text.GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, null).Size.Width;
    // get the size of one space
    var widthSpace = new NSAttributedString(" ").GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, null).Size.Width;
    var spaces = Math.Floor((maxSize.Width - widthText) / widthSpace);
    // add the spaces
    string newText = searchbar.Placeholder;
    for (double i = 0; i < spaces; i++)
    {
        newText += " ";
    }
    searchbar.Placeholder = newText;
}

-2

虽然现在已经太晚了,但如果有人仍然在寻找解决方案,可以按照以下步骤操作。

UITextField *searchTextField = [searchBarController.searchBar valueForKey:@"_searchField"];

您可以使用上面的代码来获取搜索字段。现在只需使用您想要使用的属性,比如。

searchTextField.layer.cornerRadius = 10.0f;
searchTextField.textAlignment = NSTextAlignmentLeft;

附注:文本对齐属性用于文本和占位符。

谢谢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接