为UIKeyboardTypeNumberPad增加自定义按键

在 iPhone 上面開發應用程式時, 在使用輸入鍵盤時, 或多或少都會遇到客制化鍵盤的問題, 這邊筆者以
簡單的數字鍵盤來示範客制化的動作. 這部份我想網路上已經有不少 sample code , 但大部份基本上都是
以 SDK 3.x 的版本去實作, 以"特定寫法"來實作客制化在 iOS4 會有問題, 這部份稍候會提到兩版本的差異.

上述看到的例子是 UIKeyboardTypeNumberPad 搭配 "Done" 的圖示所組合而成的. 在開
始介紹如何實作之前, 先稍微提一下網路上查到的一些範例寫法. 因為 SDK 升版之
後在架構上有做了些修改, 所以導致行為上的不正確. 以下面這例子為例, 它可以正
常的在 iOS4 之前的版本運行, 但在 iOS4 上卻會有看不到上面 "Done" 圖示的問題.

- (void)loadView{
...
textFieldContent.delegate= self;
textFieldContent.placeholder= @"press me";
textFieldContent.keyboardType= UIKeyboardTypeNumberPad;
textFieldContent.returnKeyType= UIReturnKeyDone;
[self.viewaddSubview:textFieldContent];
[textFieldContentrelease];
[[NSNotificationCenterdefaultCenter] addObserver:self
selector:@selector(keyboardWillShow:) 
name:UIKeyboardWillShowNotification
object:nil];
}

- (void)keyboardWillShowOnDelay:(NSNotification*)notification{
UIButton*doneButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
doneButton.frame= CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted= NO;
[doneButton setImage:[UIImageimageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImageimageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:selfaction:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
UIWindow* tempWindow = [[[UIApplicationsharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(inti=0; i<[tempWindow.subviewscount]; i++) {
keyboard = [tempWindow.subviewsobjectAtIndex:i];
if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
}


上述這段代碼主要原理是透過跟 OS 註冊 keyboard 相關的 notification, 並在顯示
keyboard 時, 在 keyboard view 上添加所需要的特定 UIView, 簡單流程大致如下
1. 註冊 UIKeyboardWillShowNotification : 當 keyboard 要秀時, OS 就會呼叫
    keyboardWillShow
2.  當被 keyboardWillShow 叫用時, 搜尋屬於 keyboard 的 view
   if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
3. 當找到所需要的 view 時, 再將需要的 view 加入即可
   [keyboard addSubview:doneButton];
上面就是一個 customized keyboard 的簡單實作流程. 但是為什麼這段 code 會無法
在 iOS4 上正確執行呢? 問題點主要出在上述的第 2 個步驟.
在舊的 SDK 中, 當 UIKeyboardWillShowNotification 事件發生且叫用 keyboardWillShow 
時, 此時的 keyboard view 已經被添加到 windows 裡了, 但是在 iOS4 的世界中, 相同
情況發生時, keyboard view 卻會在下個 event loop 裡才會被添加到 windows 中, 也
就是因為如此, 所以上述
[[[UIApplication sharedApplication] windows] objectAtIndex:1];
會找不到 keyboard view. 除了這原因以外, 還有另一個重要的差異性, 第 2 步驟所比
對的 @"<UIKeyboard" 字串在 iOS4 中也被修正過, 它被藏在 @"<UIPeripheralHostView"

裡.

針對這兩點, 所以將只要將之修正即可正常的在 iOS4 上執行
1. keyboard view
   既然知道是 keyboard view 會在下個 event loop 才會被放到 windows 裡, 所以我們
   可以透過下面方式將 keyboardWillShow 延遲叫用
   [self performSelector:@selector(keyboardWillShow:) withObject:nil afterDelay:0];
2. 修正比對 @"<UIKeyboard" 的方式

if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) 
possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"])  
{
foundKeyboard = possibleKeyboard;
break;
}                
經過上述兩個修正之後的 code 大概會如下 :
[[NSNotificationCenterdefaultCenter] addObserver:self
selector:@selector(keyboardWillShowOnDelay:) 
name:UIKeyboardWillShowNotification 
object:nil];
- (void)keyboardWillShowOnDelay:(NSNotification *)notification
{
[selfperformSelector:@selector(keyboardWillShow:) withObject:nilafterDelay:0]; 
}
- (void)keyboardWillShow:(NSNotification *)notification
{    
UIView *foundKeyboard = nil;
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) 
{
if (![[testWindow class] isEqual:[UIWindow class]]) 
{
keyboardWindow = testWindow;
break;
}
}
if (!keyboardWindow) return;
for (UIView *possibleKeyboard in [keyboardWindow subviews]) 
{            
//iOS3
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) 
{
foundKeyboard = possibleKeyboard;
break;
}
else
{
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) 
{
possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
}                                                                                
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) 
{
foundKeyboard = possibleKeyboard;
break;
}                
}            
}
if (foundKeyboard) 
{
// create custom button
UIButton*doneButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted= NO;
[doneButton setImage:[UIImageimageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImageimageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:selfaction:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
[foundKeyboard addSubview:doneButton];
}
}

 

 

 

 

 

 

If you have ever written an iPhone app that requires numeric input,then you surely know about the UIKeyboardTypeNumberPad. And if you haveever used that flavor of the iPhone's keyboard, then you surely knowthat it lacks one very important feature: The UIKeyboardTypeNumberPaddoes not have a "return" key.
In fact every other keyboard type (except for the pretty similarUIKeyboardTypePhonePad) does offer the possibility to be dismissed bysetting the returnKeyType property of the correspondingUITextInputTraits implementor. So how does one achieve the same effectwith the number pad? We have found a workround!
When looking at the number pad, you'll notice that there is anunused space on its bottom left. That's where we are going to plug inour custom "return" key.


To make it short: take a screenshot, cut out the whole backspacekey, flip it horizotally, clear its backspace symbol in Photoshop andoverlay it with the text that we want on our “return” key. We’ve chosento label it “DONE”. Now we have the image for our custombutton’s UIControlStateNormal. Repeat the whole procedure (with atouched backspace key when taking the screenshot) to get a second imagefor our button’s UIControlStateHighlighted. Here’s the result:
   

Now back to coding. First we need to know when the number pad isgoing to be slided up on the screen so we can plug in our custom buttonbefore that happens. Luckily there’s a notification for exactly thatpurpose, and registering for it is as easy as:
 
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(keyboardWillShow:) 
                                             name:UIKeyboardWillShowNotification 
                                           object:nil];
 [/pre]Don't forget to remove the observer from the notification center in the appropriate place once you're done with the whole thing:
 
[[NSNotificationCenter defaultCenter] removeObserver:self];[/pre]Now we’re getting to the heart of it. All we have to do in thekeyboardWillShow method is to locate the keyboard view and add ourbutton to it. The keyboard view is part of a second UIWindow of ourapplication as others have already figured out (see this thread).So we take a reference to that window (it will be the second window inmost cases, so objectAtIndex:1 in the code below is fine), traverse itsview hierarchy until we find the keyboard and add the button to itslower left:
 
- (void)keyboardWillShow:(NSNotification *)note {  
    // create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
    [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
    [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
 
    // locate keyboard view
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;
    for(int i=0; i<[tempWindow.subviews count]; i++) {
        keyboard = [tempWindow.subviews objectAtIndex:i];
        // keyboard view found; add the custom button to it
        if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
            [keyboard addSubview:doneButton];
    }
}[/pre]Voilà, that’s it! The empty space for our button starts atcoordinate (0, 163) and has the dimensions (106, 53). The doneButtonmethod has to be written now of course, but that’s not hard any more.Just make sure that you call resignFirstResponder on the text fieldthat is being edited to have the keyboard slide down.

 

 

 

 

有一种思路叫寄生...

我相信是懒人推动了世界的发展,既然iphone有了自己的软件盘,我们什么还要自己实现其功能呢。
so,只要寄生在上面就行了。

感谢alan转载的文章给的灵感。
http://www.cocoachina.com/bbs/read.php?tid-3999.html

思路:
1.用静态方法找到应用程序当前view(window)中的UIKeyboard的view
2.在键盘的view上帖上自己的view,(精彩了,这个自己的view就是你自己键盘,任意发挥,什么类型键盘都可以做了)
3.根据需要调整系统键盘的大小以满足你想要的尺寸
4.给自己的键盘view上的button添加方法,实现功能

主要代码:
添加自身类为键盘事件的观察者

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];

核心思路代码:
- (void)keyboardWillShow:(NSNotification *)note
{
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];//知识点
for(int i=0; i<[tempWindow.subviews count]; i++)
{
keyboard = [tempWindow.subviews objectAtIndex:i];
if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
{
[keyboard setFrame:CGRectMake(0, 460, 320, 345)];
[self congfigKeypad];

[keyboard addSubview:keyPadView1];

}
}
}

比如配置方法可以是这样:
-(void)congfigKeypad
{
SearBtn *one = [[SearBtn alloc] initWithFrame:CGRectMake(81, 3, kNumPadW, kNumPadH) index:1 ContextString:@"1" type:kNumPadType];
[one setImage:[UIImage imageNamed:@"1.png"] forState:UIControlStateNormal];
[one addTarget:self action:@selector(buttonClickAtIndex:) forControlEvents:UIControlEventTouchUpInside];
//......略
}

添加NSMutalbeString作为文本域字串的容器,点击button后append的button对应的字串。
- (void)buttonClickAtIndex:(id)sender
{
SearBtn *btnItem = (SearBtn*)sender;
NSString *str = btnItem->btnText;
[s_text appendString:str];
[sBar setText:s_text];
}


再实现一个deleteChar的方法作为退格键
思路:
if ([s_text length] > 0)
{
NSRange rang;
rang.location = [s_text length] - 1;
rang.length = 1;
[s_text deleteCharactersInRange:rang];
}


现在点击各种文本域,应该就可以现实自己的键盘了。

继续优化
用textfield的代理方法控制键盘的字串类型,长度,和响应消失
[ 此帖被evangel在2009-12-17 22:32重新编辑 ]
图片:图片 1.png 

图片:图片 2.png 

  

Q:如果是通过[lang=objc][/lang]来显示代码的话,就不能再编辑了,不然都是乱码……
A :也可以,要先把代码去掉提交一次,然后再加上代码修改再提交一次……

隐藏键盘

UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;
    for(int i=0; i<[tempWindow.subviews count]; i++) {
        keyboard = [tempWindow.subviews objectAtIndex:i];
        // keyboard view found; add the custom button to it
        if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
            //[keyboard addSubview:keyboardView];
            keyboard.hidden=YES;
    }

还能隐藏键盘,使用自己的view载入动画和控制位置,也不需要担心背景是否会显示出默认键盘!!lucky!!

 
多个页面应该不会有问题,切换页面时候键盘就消失了。

同一个页面的时候:
1。设置键的view为实例变量

2。给有自定义键盘的那个textfield添加delegate方法:- (void)textFieldDidEndEditing:(UITextField *)tf;
在这个方法里[myKeyPad removeFromSuperview];

3。在- (void)keyboardWillShow:(NSNotification *)note;里判断有自定键盘的textfield为firstResponder时候,再add键盘的view。
if([textField isFirstResponder])  [myKeyPad addSubview:doneButton];

当然还有很多别的方法

 

重新回复一下这个帖子,因为时间过去大半年了,我用SDK4.0,无法按照楼主的代码直接实现,而是做了一点点的修改才能实现。大家谁有时间帮忙用最新SDK测试一下,看看是不是如此。

问题与修改1
原帖中用UIKeyboardWillShowNotification,tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1] 的subview数目为0!
我改UIKeyboardDidShowNotification,一切正常。

问题与修改2
原帖中用了字符串@"<UIKeyboard"来检测键盘的view,在我这不管用。
我改用了@"<UIPeripheralHostView"

结果:

修改后,在SDK4.0的模拟器和真机上测试ok!

 

转载于:https://www.cnblogs.com/pengyingh/articles/2418150.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

车载安卓中控改鸿蒙,教你改装车子中控安卓大屏,看一遍你就会了,改完后低配秒变高配...

因为我这个车子年代比较久了&#xff0c;所以没有中控大屏&#xff0c;需要导航的时候我都是把手机放在出风口支架这个地方&#xff0c;这种磁吸的支架有时候过减速杠一震动就掉下来了&#xff0c;我又不想在上面粘什么东西&#xff0c;所以干脆就花几百块钱买了一个能够插手机…

pip 删除安装包_Python中PIP的快速指南

无论您是Python新手还是有经验的Python开发人员&#xff0c;不使用pip安装命令是不可能编写或开发Python应用程序的。在这篇文章中&#xff0c;我将对Pip进行详细介绍。Pip是Python Package Manager的缩写。当您在系统上安装python时&#xff0c;它附带了一组预定义的包&#x…

元素不包括_干货 | FDA法规对元素杂质的限度控制及计算方法

元素杂质又称重金属&#xff0c;重金属原义指比重大于5的金属&#xff0c;元素杂质包括可能存在于原料、辅料或制剂中&#xff0c;来源于合成中催化剂残留、药品生产制备过程中引入或辅料中存在的、生产设备引入、或容器密闭系统引入。某些元素杂质不仅对药品的稳定性、保质期产…

web 日志分析工具 awstats 简单安装

awstats安装使用awstats是一个开源的日志分析工具&#xff0c;用perl编写。感觉还不错&#xff0c;把安装记录写下&#xff0c;也许有人用的到。可以分析大部分标准日志数据&#xff0c;如apache的&#xff0c;nginx的都可以首先下载awstats工具&#xff0c;http://awstats.sou…

MyOffic(经理评分)

1 public class SE2 {3 //员工类4 private int id;5 6 public int Id7 {8 get { return id; }9 set { id value; } 10 } 11 private string name; 12 13 public string Name 14 …

win7讲述人修复_揭秘:干掉了win7!为何win10屡被吐槽它却“永世留芳”

干掉了win7系统&#xff0c;win10似是更加地“肆无忌惮”了&#xff01;自微软宣布停止Windows 7的全部支持&#xff0c;而后win7的老用户越发频繁地收到win10的升级通知。要知道&#xff0c;“停止全部支持”也就意味着win7不再有任何新特性&#xff0c;在安全方面也不再能得到…

实现图片打乱_2020 回顾 | 25张图片,记录潮州的这一年

一年将近&#xff0c;万物更新这一年&#xff0c;不简单&#xff0c;也不容易让我们把时针拨回到1月通过镜头来回顾潮州这一年来令人难忘、激动和高光的时刻// 1月 //- January - 1月份的潮州充满了年味大家都沉浸在迎接新年的喜悦心情中期盼着新年的到来突如其来的疫情打乱了所…

如何导出SQL Azure脚本?

1). Tasks—Generate Scripts 2). In the “Generate and Publish Scripts” dialog, Next -- Next 3).Click “Advanced”, set likes following: 转载于:https://www.cnblogs.com/RobotTech/archive/2012/03/28/2420707.html

jh锂电保护电路_一文弄懂,锂电池的充电电路,以及它的保护电路方案设计

锂电池特性首先&#xff0c;芯片哥问一句简单的问题&#xff0c;为什么很多电池都是锂电池&#xff1f;锂电池&#xff0c;工程师对它都不会感到陌生。在电子产品项目开发的过程中&#xff0c;尤其是遇到电池供电的类别项目&#xff0c;工程师就会和锂电池打交道。这是因为锂电…

as上的git到码云操作_如何使用git从码云克隆项目到本地?

https://www.cnblogs.com/gbb123/p/6784822.html前段时间&#xff0c;有读者微信问我&#xff0c;如果使用Git从码云或者Github 克隆代码到本地&#xff0c;然后进行提交代码的操作 。可能是新手&#xff0c;刚接触编程&#xff0c;我就从网上找到了这篇文章给他看&#xff0c;…

ruijie交换机lacp动态_Server2016和华为s5720交换机链路聚合增加带宽

一、 背景1、server端企业中一台server2016利用两块1G网卡组成teaming生成一张2G的虚拟网卡&#xff0c;业务数据在这张带宽为2G的虚拟网卡上运行。这块网卡不仅带宽可以提升1倍&#xff0c;而且可以实现冗余&#xff0c;负载均衡&#xff0c;故障自动切换&#xff0c;保证业务…

如何用Netty实现一个轻量级的HTTP代理服务器

为什么会想通过Netty构建一个HTTP代理服务器&#xff1f;这也是笔者发表这篇文章的目的所在。 其主要还是源于解决在日常开发测试过程中&#xff0c;一直困扰测试同学很久的一个问题&#xff0c;现在我就来具体阐述一下这个问题。 在日常开发测试过程中&#xff0c;为了确保上线…

hello my first blog

2019独角兽企业重金招聘Python工程师标准>>> <?phpfunction hello {echo hello world;} 转载于:https://my.oschina.net/guanyue/blog/52043

python 钉钉机器人发送图片_Python结合钉钉实时自动监控股票行情,上班炒股再也不怕老板发现...

最近全球股市开始回暖&#xff0c;之前清仓的股民现在又陆续开始建仓。股市交易时间&#xff0c;一般也是上班时间&#xff0c;频繁的查看股票软件不仅会影响工作效率&#xff0c;也容易被老板以为工作不饱和。所以&#xff0c;我们就借助python的强大功能&#xff0c;把提前设…

IDEA MAVEN Project 显示问题

今天正常打开idea&#xff0c;却发现maven窗口找不到了&#xff1a;试了这些方法 首先idea自带了maven控件&#xff0c;不像Eclipse还需要下载控件&#xff0c;如果你以前有maven在右边&#xff0c;出于某种原因&#xff0c;消失找不到 了&#xff0c;你可以试试我写的方法。 …

画图调子图间距_好看好用的桥梁工程图,你值得拥有!

来源&#xff1a;筑龙路桥设计桥梁工程图的内容1.桥位地形、地物、地质及水文资料图&#xff0c;用来表示桥梁位置及周边关系的图纸。桥位平面图、桥位地质断面图。2.桥梁总体布置图&#xff0c;表示桥梁整体形状、大小、结构的图纸。立面图、侧立面图。3.桥梁的上部、下部构造…

MySQL 调用存储过程

1&#xff1a;存储过程返回值 View Code public void InputOutputParameters() { AdoHelper ado AdoHelper.CreateHelper(DbProvideType.MySql); ado.ExecuteNonQuery(conn, CommandType.Text, "CREATE PROCEDURE spTest1( INOUT strVal V…

佳博热敏条码打印机修改ip_高赋码热转印打印和热敏打印区别

在热转印打印中&#xff0c;热敏打印头给色带加热&#xff0c;油墨熔化在标签材料上以形成图案。色带材料被介质吸收&#xff0c;图案构成了标签的一部分。该技术提供了其他按需式打印技术无法匹敌的图案质量和耐久性。与热敏打印机相比&#xff0c;热转印打印机可接受更多品种…

cocos2d的常用动作及效果总结之五:Animation

这一篇是讲一下如何在cocos2d中实现动画。 实现动画的步骤&#xff1a; 加载帧生成动画对象运行动画加载帧我用过两种方式&#xff1a; 第一种是使用.plist文件&#xff0c;通过CCSpriteFrameCache读取动画帧&#xff0c;并加载到CCAnimation对象中&#xff0c;如下&#xff1a…

雷鸟html签名设置,thunderbird 使用OpenPGP加解密邮件

一、添加插件Enigmail二、进行密钥管理&#xff0c;并创建->新密钥对三、选择账户&#xff0c;选择有无密码&#xff0c;创建密钥。根据提示选择是否要撤销文件。选择无密码创建密钥对速度快。最好选择生成撤销证书&#xff0c;在以后密钥对无用时告诉密钥服务器撤销无效公钥…