Oto mój zwyczaj klawiatura, która wierzę adresy je jako zupełnie jak Apple pozwoli:
// PVKeyboard.h
#import <UIKit/UIKit.h>
@interface PVKeyboard : UIView
@property (nonatomic,assign) UITextField *textField;
@end
// PVKeyboard.m
#import "PVKeyboard.h"
@interface PVKeyboard() {
UITextField *_textField;
}
@property (nonatomic,assign) id<UITextInput> delegate;
@end
@implementation PVKeyboard
- (id<UITextInput>) delegate {
return _textField;
}
- (UITextField *)textField {
return _textField;
}
- (void)setTextField:(UITextField *)tf {
_textField = tf;
_textField.inputView = self;
}
- (IBAction)dataPress:(UIButton *)btn {
[self.delegate insertText:btn.titleLabel.text];
}
- (IBAction)backPress {
if ([self.delegate conformsToProtocol:@protocol(UITextInput)]) {
[self.delegate deleteBackward];
} else {
int nLen = [_textField.text length];
if (nLen)
_textField.text = [_textField.text substringToIndex:nLen-1];
}
}
- (IBAction)enterPress {
[_textField.delegate textFieldShouldReturn:_textField];
}
- (UIView *)loadWithNIB {
NSArray *aNib = [[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
UIView *view = [aNib objectAtIndex:0];
[self addSubview:view];
return view;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
[self loadWithNIB];
return self;
}
@end
w Xcode 4.3 i później, trzeba stworzyć obiektywną-klasa (dla plików .h & .M) na podstawie UIView i pliku widoku interfejsu użytkownika (dla pliku .xib). Upewnij się, że wszystkie trzy pliki mają tę samą nazwę. Używając Inspektora tożsamości, upewnij się, że ustawiono klasę niestandardową właściciela pliku XIB, aby pasowała do nazwy nowego obiektu. Korzystając z Inspektora atrybutów, ustaw rozmiar formularza na Freeform i ustaw opcję Pasek stanu na none. Korzystając z Inspektora rozmiarów, ustaw rozmiar formularza, który powinien odpowiadać szerokości standardowej klawiatury (320 dla portretu iPhone'a i 480 dla krajobrazu iPhone'a), ale możesz wybrać dowolną wysokość.
Formularz jest gotowy do użycia. Dodaj przyciski i podłącz je odpowiednio do danych dataPress, backPress i enterPress. Funkcje initWithFrame: i loadWithNIB wykonają całą magię, aby umożliwić korzystanie z klawiatury zaprojektowanej w Interface Builder.
Aby skorzystać z tej klawiatury z UITextField myTextField, wystarczy dodać następujący kod do viewDidLoad:
self.keyboard = [[PVKeyboard alloc]initWithFrame:CGRectMake(0,488,320,60)];
self.keyboard.textField = self.myTextField;
powodu pewnych ograniczeń, to klawiatura nie jest wielokrotnego użytku, więc trzeba po jednym w każdym polu. Mogę sprawić, że będzie to wielokrotnego użytku, ale po prostu nie czuję się tak sprytnie. Klawiatura jest również ograniczona do UITextFields, ale wynika to głównie z ograniczeń implementacji funkcji klawisza Enter, które wyjaśnię poniżej.
Oto magia, która powinna pozwalają zaprojektować lepszą klawiaturę niż te ramy rozrusznika ...
I zostały wdrożone jedyną własność tej klawiatury textField, stosując dyskretny dyskretny setter (setTextField), ponieważ :
- musimy obiekt UITextField do obsługi wejść problemu
- musimy UITextField ponieważ jest on zgodny z protokołem UITextInput zgodnego UIKeyInput, który robi dużo naszego podnoszenia ciężkich
- było to wygodne miejsce do ustawienia pola inputView UITextInput, aby użyć tej klawiatury.
Zauważysz drugą własność prywatną o nazwie delegat, która zasadniczo powoduje typowanie wskaźnika UITextField do wskaźnika UITextInput. Prawdopodobnie mógłbym obsłużyć tę obsadę w linii, ale wyczułem, że może to być przydatne jako funkcja przyszłej ekspansji, być może włączając obsługę UITextView.
Funkcja danePress wprowadza tekst do edytowanego pola przy użyciu metody insertText dla UIKeyInput. To wydaje się działać we wszystkich wersjach z powrotem do iOS 4. Dla mojej klawiatury, po prostu używam etykiety każdego przycisku, co jest całkiem normalne. Użyj dowolnego NSStringsa, który ci się podoba.
Funkcja functionBack wykonuje backspace i jest nieco bardziej skomplikowana. Kiedy UIKeyInput deleteBackward działa, działa cudownie. I chociaż dokumentacja mówi, że działa z systemem iOS 3.2, wydaje się, że działa tylko z systemem iOS 5.0, czyli wtedy, gdy UITextField (i UITextView) są zgodne z protokołem UITextInput. Więc przedtem jesteś sam. Ponieważ obsługa iOS 4 jest problemem dla wielu osób, zaimplementowałem lame backspace, który działa bezpośrednio na UITextField. Gdyby nie to wymaganie, mogłem sprawić, by klawiatura działała z UITextView. A ten backspace nie jest tak ogólny, usuwając tylko ostatni znak, podczas gdy deleteBackward będzie działał poprawnie, nawet jeśli użytkownik przesunie kursor.
Funkcja enterPress implementuje klawisz Enter, ale jest kompletnym kluderem, ponieważ Apple wydaje się nie podawać metody wywoływania klawisza Enter. Zatem enterPress po prostu wywołuje funkcję delegującą UITextField textFieldShouldReturn :, którą programuje większość programistów. Należy pamiętać, że delegatem jest tutaj UITextFieldDelegate dla UITextField, a NIE właściwość delegata dla samej klawiatury.
Rozwiązanie to obejmie normalne przetwarzanie klawiatury, co nie ma większego znaczenia w przypadku UITextField, ale czyni tę technikę bezużyteczną z UITextView, ponieważ istnieje teraz sposób wstawiania łamania linii w edytowanym tekście.
To wszystko. Aby to zadziałało, potrzeba było 24 godzin czytania i brukowania. Mam nadzieję, że to pomoże komuś.
Chociaż ja odpowiadając na komentarz, mam jedną dla ciebie. :) Twoja metoda 'enterPress' ma jedną niewielką wadę. Zakłada, że 'UITextFieldDelegate' implementuje metodę' textFieldShouldReturn: '. To nie może być bezpieczne założenie. – rmaddy
Odpowiadasz na własne pytanie? – sunkehappy
@rmaddy Tak, zrobiłem to założenie (mówię tak samo w tekście, ponieważ wszyscy jesteśmy prawie zobowiązani do złożenia rezygnacji jako Pierwszy Odpowiadający i być może wybieramy następne pole, aby stać się Pierwszym Odpowiadającym). Ale masz rację, byłoby bezpieczniej/lepiej sprawdzić, aby upewnić się, że metoda istnieje przed wywołaniem. –