原创-iOS让UISeartchBar占位文与点击编辑时内容起始位置还有光标位置一致

好久没有写文章分享点什么了。之前在项目中曾经遇到测试人员提出的一个关于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感兴趣的人互相交流,互相进步!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,952评论 4 60
  • 一、简介 <<UITextField(文本框) : UITextField被用作项目中获取用户信息的重要控件.在A...
    无邪8阅读 5,411评论 0 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,140评论 25 707
  • 就目前来说,我感觉你对于具体的职业内容的渴望远不及你对于能从职业中所获得的认同感多。所以,我觉得工作内容排在其次,...
    郦三游阅读 315评论 0 0
  • 今年回家坐在一桌嗑瓜子摇微信没有听到任何唠叨心里一颗大石终于落下了,心里头一痛快就喜滋滋的递过松子给我娘:...
    林果儿shirley阅读 896评论 5 4