iOS用のカスタム入力用のキーボードの作成

標準ライブラリは、 UITextField



UITextView



いくつかの異なるタイプのキーボードを提供しUITextField



その中には、通常のメール、URL(通常のものとは数文字異なる)、電話(デジタル)があります。 ほとんどの生活状況では、これで十分ですが、常にではありません。



アプリケーションに、数値と算術式を受け入れることができる入力フィールドがあると想像してください。



電話のキーボードでは十分ではありません-意味がなく、すべての操作記号などがありません。



もちろん、必要なものはすべて通常のキーボード上にありますが、この場合は95%は使用されません(数値と算術演算の記号だけが必要なことを思い出してください)。



結論はそれを示唆しています:キーボードを書く必要があります。







それでは、どのようなキャラクターが必要ですか? 「.0123456789%+-×÷」、およびコレクションには「↵」(リターン)と「←」(バックスペース)を追加します。 レイアウトを描く:







いいですね 次に、このことをテキスト入力フィールドにねじ込む必要があります。



iOS 3以降、入力を許可するインターフェースコンポーネント( UITextField



UITextView



)には、 inputView



inputAccessoryView



素晴らしいプロパティがありinputAccessoryView







inputAccessoryView



にあるinputAccessoryView



は、キーボードの上に表示されます(もちろん、キーボードが画面上にある場合)。 これは通常、一対のボタンや入力フィールドを持つツールバーです。



ただし、 inputView



は標準キーボードを再定義するためのものです。 つまり、 UIView



クラスのオブジェクトUIView



このプロパティに割り当てた場合、テキストフィールドがfirstResponder



になると、表示されるのはキーボードではなく、 firstResponder



にある同じUIView



オブジェクトになりinputView



。 通常のキーボードと同じ場所(下、へへ)に同じアニメーションで表示されます。 さらに、 UIKeyboardWillShowNotification



などの通知も送信されます! 固体プラス。



しかし、短所はどうですか? 私はそれらを持っています。



非標準入力の主な欠点は、キーボードとテキストボックス間の接続を整理する方法です。 多くの解決策を思い付くことができますが、もちろん、使用するために可能な限り透明に入力を「ネイティブ」にすることが理想的です(たとえば、 UITextInputTraits



プロトコルとUIKeyboardType



拡張機能を使用したシャーマニズム)。 残念ながら、私はそれについてあまり考えませんでしたが、時間があれば、私は間違いなくそれを終了しようとします。



最も明白な解決策の1つはデリゲートです。 キーボードは、どのボタンが押されたかを単にデリゲートに伝えます。 そして、ボタンについては。 キーボードをハードコーディングして、動的に構成できるようにしないのはなぜですか? 確かに、なぜですか? このためのDatasourceプロトコルを取得しましょう。



したがって、1つのクラスと2つのプロトコル(キーボード、デリゲート、データソース)になります。

 //KHKeyboard.h #import <UIKit/UIKit.h> #import "KHKeyboardDatasource.h" #import "KHKeyboardDelegate.h" @interface KHKeyboard : UIView @property (nonatomic, assign) id<KHKeyboardDatasource> datasource; @property (nonatomic, assign) id<KHKeyboardDelegate> delegate; @end //KHKeyboardDelegate.h #import <UIKit/UIKit.h> @class KHKeyboard; @protocol KHKeyboardDelegate <NSObject> @optional - (void)keyPressedInKeyboard:(KHKeyboard *)keyboard atIndex:(NSInteger)index; @end //KHKeyboardDatasource.h #import <UIKit/UIKit.h> @class KHKeyboard; @protocol KHKeyboardDatasource <NSObject> @required - (NSInteger)numberOfKeysInKeyboard:(KHKeyboard *)keyboard; - (UIButton *)buttonForKeyInKeyboard:(KHKeyboard *)keyboard atIndex:(NSInteger)index; @end
      
      





デリゲートではすべてが明確です-押されたボタンはインデックスによって決定されます。 データソースは、キーボードを構成するように設計されています。ボタンの数を報告し、 UIButton



オブジェクト(ボタン自体)も提供しUIButton



。 返されたボタンを設定する場合、 frame



プロパティを設定することを忘れないでください-ビュー上のボタンの位置を決定します。



初期化:

 self.rects = [NSArray arrayWithObjects: [NSValue valueWithCGRect:CGRectMake(0, 0, 64, 50)], [NSValue valueWithCGRect:CGRectMake(64, 0, 64, 50)], [NSValue valueWithCGRect:CGRectMake(128, 0, 64, 50)], [NSValue valueWithCGRect:CGRectMake(192, 0, 64, 50)], [NSValue valueWithCGRect:CGRectMake(256, 0, 64, 50)], [NSValue valueWithCGRect:CGRectMake(0, 50, 64, 50)], [NSValue valueWithCGRect:CGRectMake(64, 50, 64, 50)], [NSValue valueWithCGRect:CGRectMake(128, 50, 64, 50)], [NSValue valueWithCGRect:CGRectMake(192, 50, 64, 50)], [NSValue valueWithCGRect:CGRectMake(256, 50, 64, 50)], [NSValue valueWithCGRect:CGRectMake(0, 100, 64, 50)], [NSValue valueWithCGRect:CGRectMake(64, 100, 64, 50)], [NSValue valueWithCGRect:CGRectMake(128, 100, 64, 50)], [NSValue valueWithCGRect:CGRectMake(192, 100, 64, 50)], [NSValue valueWithCGRect:CGRectMake(256, 100, 64, 100)], [NSValue valueWithCGRect:CGRectMake(0, 150, 128, 50)], [NSValue valueWithCGRect:CGRectMake(128, 150, 64, 50)], [NSValue valueWithCGRect:CGRectMake(192, 150, 64, 50)], nil]; self.titles = [NSArray arrayWithObjects: @"7", @"8", @"9", @"×", @"←", @"4", @"5", @"6", @"÷", @"%", @"1", @"2", @"3", @"+", @"↵", @"0", @".", @"−", nil]; KHKeyboard *keyboard = [[[KHKeyboard alloc] init] autorelease]; keyboard.datasource = self; keyboard.delegate = self; self.textField.inputView = keyboard;
      
      





データソースの構成:

 - (NSInteger)numberOfKeysInKeyboard:(KHKeyboard *)keyboard { return [self.rects count]; } - (UIButton *)buttonForKeyInKeyboard:(KHKeyboard *)keyboard atIndex:(NSInteger)index { NSString *title = [self.titles objectAtIndex:index]; CGRect rect = [(NSValue *)[self.rects objectAtIndex:index] CGRectValue]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = rect; [button setTitle:title forState:UIControlStateNormal]; [button setUserInteractionEnabled:NO]; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [button setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted]; [button setReversesTitleShadowWhenHighlighted:YES]; if (index == 14) { // return key [button setBackgroundImage:[UIImage imageNamed:@"button_normal_2.png"] forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:@"button_highlighted_2.png"] forState:UIControlStateHighlighted]; } else if (index == 15) { // "0" key [button setBackgroundImage:[UIImage imageNamed:@"button_normal_1.png"] forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:@"button_highlighted_1.png"] forState:UIControlStateHighlighted]; } else { [button setBackgroundImage:[UIImage imageNamed:@"button_normal.png"] forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:@"button_highlighted.png"] forState:UIControlStateHighlighted]; } [button.titleLabel setFont:[UIFont boldSystemFontOfSize:16]]; return button; }
      
      





そして孤独な代理人:

 - (void)keyPressedInKeyboard:(KHKeyboard *)keyboard atIndex:(NSInteger)index { if (index == 14) { // return key [self.textField resignFirstResponder]; } else if (index == 4) { // backspace key NSInteger length = [self.textField.text length]; if (length == 0) { return; } else { NSString *newValue = [self.textField.text substringToIndex:length - 1]; self.textField.text = newValue; } } else { NSString *value = [self.titles objectAtIndex:index]; NSMutableString *newValue = [NSMutableString stringWithFormat:@"%@%@", self.textField.text, value]; self.textField.text = newValue; } }
      
      





結果は記事の冒頭のスクリーンショットで見ることができ、またgithubで感じることもできます。



これは原則として完了できたはずですが、いくつかの疑問が残ります。



たとえば、この実装は、カスタムキーボードを必要とする入力フィールドが1つしかない場合に適しています。 そして、いくつかある場合は? 結局のところ、現時点でどれがfirstResponder



であるかを何らかの方法で決定する必要があります。



または、キーボードの外観に関する前述の通知に従うことができます(それらがどこにも消えないことを忘れないでください)。 NSNotification



クラスのobject



object



プロパティには、キーボードを呼び出したコントロールが含まれます。 したがって、保存して後でkeyPressedInKeyboard:atIndex:



で使用しますkeyPressedInKeyboard:atIndex:







この仕事を改善し、統一するための有用な願いとヒントに感謝します。



All Articles