美文网首页代码片段iOS备忘录iOS 控件定制
原创-iOS让UISeartchBar占位文与点击编辑时内容起始

原创-iOS让UISeartchBar占位文与点击编辑时内容起始

作者: 且伴诗酒共年华 | 来源:发表于2017-03-14 15:01 被阅读106次

好久没有写文章分享点什么了。之前在项目中曾经遇到测试人员提出的一个关于UISeartchBar的体验问题。相信在很多项目中我们都会用到这个搜索控件,系统默认的该控件效果是占位文字是居中显示,但是一旦我们选中进入编辑状态后,光标位置和文字输入的位置就跑到左边去了,测试给出的需求就是占位文字和编辑文字时的光标位置还有内容起始位置一律左对齐。曾经自定义过很多种控件,一想到改变这种系统自带控件的某些内容元素位置时,相信稍有一些经验的iOS开发人员一般都会想到需要自定义,最初我也是自定义了一个UISeartchBar,但是发现它没有类似于button自定义时可以返回内部label与imageView的frame的方法。因为UISeartchBar内部的那个可编辑的控件就是个textField,所以想直接重写seartchBar类似直接返回这个textField的frame方法这条路是走不通了(之前搜索相关资料得知:可能是因为UISeartchBar中的那个textField控件在早一些的版本中是直接被封装在seartchBar里,后来系统又多做了一层封装,把这个控件封装到了一个view里,封装的更深了就不能直接设置它的位置了)。最初也从网上搜索相关的问题,但一直没找到合适的解决办法,后来想到textField在自定义时有返回光标位置/占位文位置的方法,于是就想能不能把UISeartchBar中那个系统类型的textField替换成我们自定义的textField,那样,这个问题就迎刃而解了。
之前在某iOS交流群也遇到有人问类似问题的解决办法,也是网上搜了一堆到头来也没解决问题。让他试了下我的这个办法,确实也解决了问题。现在跟大家分享一下,希望能帮到更多遇到类似问题的人。好了,说了这么多废话,该切入我们的主题了。
需求描述:要让UISeartchBar的占位文与点击进入编辑状态后的光标位置/输入文字的人起始位置都要左对齐(即都在同一起始位置)。
步骤一:
首先需要我们自定义一个继承自UITextField的控件,在该文件中重写三个方法,代码如下。

#import "SeartchTextField.h"

@implementation SeartchTextField

 - (void)layoutSubviews{
    [super layoutSubviews];
   CGRect rect = self.leftView.frame;
   rect.origin.x = 10;
   self.leftView.frame = rect;
   self.leftViewMode = UITextFieldViewModeAlways;
  }//这里之所以要设置textField的左视图的位置,是因为seartchBar默认左视图是一个放大镜,如果我们自定义左对齐的话,需要让这个左视图不能与下面的三个位置出现重叠,所以在该方法中需要设置一下左视图的起始位置。

  //控制placeHolder的位置
 -(CGRect)placeholderRectForBounds:(CGRect)bounds
   {
     CGRect inset = CGRectMake(30, bounds.origin.y,bounds.size.width-30, bounds.size.height);
      return inset;
   }//这里的宽度减去30的原因是我们自定义的起始位置x值为30,如果不减去的话一旦文字内容过长,就会超出控件自身的长度,下面两个方法宽度减去30也是类似的考虑,下面就不再解释。

  //控制显示文本的位置
 -(CGRect)textRectForBounds:(CGRect)bounds
   {
      CGRect inset = CGRectMake(30, bounds.origin.y,bounds.size.width-30, bounds.size.height);
      return inset;
   }

  //控制编辑文本的位置
 -(CGRect)editingRectForBounds:(CGRect)bounds
   {
      CGRect inset = CGRectMake(30, bounds.origin.y, bounds.size.width-30, bounds.size.height);
      return inset;
   }

  @end


   这一步操作就是自定义了一个左对齐的textField,那么下一步就是要把seartchBar自带的那个UITextField类型的控件替换成我们自定义的这个textField。因此我们需要自定义seartchBar了。

步骤二:自定义UISeartchBar,将自带系统类型的textField替换成我们自定义的。代码如下:

#import "MySearchBar.h"
#import <OBJC/runtime.h>
#import "SeartchTextField.h"

@implementation MySearchBar

- (void)layoutSubviews{
    [super layoutSubviews];

    UITextField *searchField = [self  valueForKey:@"_searchField"];

    object_setClass(searchField, [SeartchTextField class]);
   searchField.returnKeyType = UIReturnKeySearch;
   //不输入文字时,禁用搜索按钮
   searchField.enablesReturnKeyAutomatically = YES;
  }
@end

代码中相信写的已经很清楚了,这里的核心代码其实就两步,一是通过KVC获取UISeartchBar自带的那个UITextField类型的文本框,然后通过运行时动态将其类型替换成我们自定义的textField即可。之所以写在layoutSubviews方法中,主要是考虑到在该方法之前,seartchBar的子控件都已经创建完毕,在这里通过kvc一定可以获取它内部的那个textField。
另外补充一点:这里用运行时的好处是,我们这里改变的是seartchBar自带textField的对象类型,而并没有改变seartchBar内部对这个子控件的设置,这样既保留了原来的效果,又通过子类继承的办法加入了我们自己想要的效果,这也正好利用了多态的特性(因为它的声明类型还是UITextField类型)。
下一步就是把系统的UIseartchBar换成我们自定义这个seartch
Bar,问题就会迎刃而解了。由于目前用的是OC语言,当然也做过swift版的测试(这里就不再贴swift版的代码了,原理是一样的),都没有问题。所以,遇到类似问题的童鞋,可以尝试下我的这种思路。

此文章为原创,希望可以和更多对iOS感兴趣的人互相交流,互相进步!

相关文章

网友评论

    本文标题:原创-iOS让UISeartchBar占位文与点击编辑时内容起始

    本文链接:https://www.haomeiwen.com/subject/fsfhnttx.html