需求背景
最近做一个搜索用户的功能,这里使用了UISearchBar。由于搜索的方式只有手机号码,所以这里的键盘要限制为数字输入,可以这么做:
<code class="language-Objective-C hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">self<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.searchBar</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.keyboardType</span> = UIKeyboardTypeNumberPad<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
但是这里有个问题,就是数字键盘上面没有“搜索”按钮,这样子用户在输入完手机号码后无法搜索。所以这个时候我们需要自己添加一个自定义的搜索按钮,然后加到键盘上面。
解决思路
- 自定义搜索button
- 监听键盘出现的事件
- 遍历搜索的Windows窗体,找到键盘的窗体,然后遍历其子视图,找到我们真正需要的键盘视图
- 把我们自定义的按钮加到上面找到的视图里
这里要注意的一点,随着iOS SDK的不断发展,keyboard的视图名称也不断在更新变化,当你调试以下代码无法得到期待的效果时,请重新遍历一次窗台,然后慢慢调试,找到真正需要的视图名称。
解决代码
1.自定义搜索按钮
<code class="hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">// 搜索按钮 _searchButton = [UIButton buttonWithType:UIButtonTypeCustom]; _searchButton.frame = CGRectMake(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">163</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">106</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">53</span>); [_searchButton <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span>Title:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"搜索"</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>State:UIControlStateNormal]; [_searchButton <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span>TitleColor:[UIColor blackColor] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>State:UIControlStateNormal]; [_searchButton addTarget:self action:@selector(SearchButtonDidTouch:) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>ControlEvents:UIControlEventTouchUpInside]; </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
2.监听键盘出现的事件
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">[[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNotificationCenter</span> defaultCenter] addObserver:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(keyboardWillShowOnDelay:) name:UIKeyboardWillShowNotification object:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)keyboardWillShowOnDelay:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNotification</span> *)notification { [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(keyboardWillShow:) withObject:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span> afterDelay:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
这里面监听通知后的执行函数并非立马执行查找窗体的函数,是因为在iOS4后,键盘添加到窗体的事件放到了下一个EventLoop,所以我们采用了延迟的方法。
3. 遍历视图,并添加按钮
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)keyboardWillShow:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNotification</span> *)notification { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span> *foundKeyboard = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span> *keyboardWindow = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span> *testWindow in [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> sharedApplication] windows]) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (![[testWindow class] isEqual:[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span> class]]) { keyboardWindow = testWindow; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; } } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!keyboardWindow) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (__<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span> *possibleKeyboard in [keyboardWindow subviews]) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ([[possibleKeyboard description] hasPrefix:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<UIInputSetContainerView"</span>]) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (__<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span> *possibleKeyboard_2 in possibleKeyboard<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.subviews</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ([possibleKeyboard_2<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.description</span> hasPrefix:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<UIInputSetHostView"</span>]) { foundKeyboard = possibleKeyboard_2; } } } } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (foundKeyboard) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ([[foundKeyboard subviews] indexOfObject:_searchButton] == <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNotFound</span>) { [foundKeyboard addSubview:_searchButton]; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { [foundKeyboard bringSubviewToFront:_searchButton]; } } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>
这样子我们就完成了添加自定义按钮的需求了。
如果什么不正确的地方,欢迎指教。
本文解决思路主要参考网上许多前辈的解决思路,在此感谢他们的贡献!