私はこのツールバーを実装しようとしています。上部のtextFieldがfirstResponderの場合は「次へ」ボタンのみが有効になり、下部のtextFieldがfirstResponderの場合は「前へ」ボタンのみが有効になります。
それは一種の作品ですが、起こっていることは、反対のボタンを有効/無効にするために毎回2回「前へ」/「次へ」ボタンをタップする必要があることです。
これを起こしているレスポンダーチェーンに何か不足していますか?
これが私のコードです:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.topText becomeFirstResponder];
}
- (UIToolbar *)keyboardToolBar {
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];
UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]];
[segControl setSegmentedControlStyle:UISegmentedControlStyleBar];
segControl.momentary = YES;
segControl.highlighted = YES;
[segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)];
[segControl setEnabled:NO forSegmentAtIndex:0];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:segControl];
NSArray *itemsArray = @[nextButton];
[toolbar setItems:itemsArray];
return toolbar;
}
- (void)changeRow:(id)sender {
int idx = [sender selectedSegmentIndex];
if (idx == 1) {
[sender setEnabled:NO forSegmentAtIndex:1];
[sender setEnabled:YES forSegmentAtIndex:0];
self.topText.text = @"Top one";
[self.bottomText becomeFirstResponder];
}
else {
[sender setEnabled:NO forSegmentAtIndex:0];
[sender setEnabled:YES forSegmentAtIndex:1];
self.bottomText.text =@"Bottom one";
[self.topText becomeFirstResponder];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if (!textField.inputAccessoryView) {
textField.inputAccessoryView = [self keyboardToolBar];
}
}
さて、見事な BSKeyboardControls を調べた後、textFieldDidBeginEditing
に、@selector
の場所ではなく、セグメント化されたコントロールの有効化と無効化を実装してみました。セグメント化されたコントロールの変数も導入しました。現在は機能しています。修正されたコードスニペットは次のとおりです。
- (void)viewDidLoad
{
[super viewDidLoad];
[self.topText becomeFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (UIToolbar *)keyboardToolBar {
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];
self.segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]];
[self.segControl setSegmentedControlStyle:UISegmentedControlStyleBar];
self.segControl.momentary = YES;
[self.segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)];
[self.segControl setEnabled:NO forSegmentAtIndex:0];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:self.segControl];
NSArray *itemsArray = @[nextButton];
[toolbar setItems:itemsArray];
return toolbar;
}
- (void)changeRow:(id)sender {
int idx = [sender selectedSegmentIndex];
if (idx) {
self.topText.text = @"Top one";
[self.bottomText becomeFirstResponder];
}
else {
self.bottomText.text =@"Bottom one";
[self.topText becomeFirstResponder];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if (!textField.inputAccessoryView) {
textField.inputAccessoryView = [self keyboardToolBar];
}
if (textField.tag) {
[self.segControl setEnabled:NO forSegmentAtIndex:1];
[self.segControl setEnabled:YES forSegmentAtIndex:0];
}
}
これはUIViewController
拡張機能で、入力アクセサリを介してナビゲーションを提供するためにUITextField
sのグループが必要なときに使用します。このアプローチでUITextField
委任を使用する必要はありません。複数のフォームに動作を追加すると、単一のライナーになります。 「終了」ボタンを閉じて閉じることもできます。
extension UIViewController {
func addInputAccessoryForTextFields(textFields: [UITextField], dismissable: Bool = true, previousNextable: Bool = false) {
for (index, textField) in textFields.enumerated() {
let toolbar: UIToolbar = UIToolbar()
toolbar.sizeToFit()
var items = [UIBarButtonItem]()
if previousNextable {
let previousButton = UIBarButtonItem(image: UIImage(named: "Backward Arrow"), style: .plain, target: nil, action: nil)
previousButton.width = 30
if textField == textFields.first {
previousButton.isEnabled = false
} else {
previousButton.target = textFields[index - 1]
previousButton.action = #selector(UITextField.becomeFirstResponder)
}
let nextButton = UIBarButtonItem(image: UIImage(named: "Forward Arrow"), style: .plain, target: nil, action: nil)
nextButton.width = 30
if textField == textFields.last {
nextButton.isEnabled = false
} else {
nextButton.target = textFields[index + 1]
nextButton.action = #selector(UITextField.becomeFirstResponder)
}
items.append(contentsOf: [previousButton, nextButton])
}
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: view, action: #selector(UIView.endEditing))
items.append(contentsOf: [spacer, doneButton])
toolbar.setItems(items, animated: false)
textField.inputAccessoryView = toolbar
}
}
}
例:
let field1 = UITextField()
let field2 = UITextField()
addInputAccessoryForTextFields([field1, field2], dismissable: true, previousNextable: true)
これが妥当な 矢印アイコン です。
迅速:
lazy var inputToolbar: UIToolbar = {
var toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.translucent = true
toolbar.sizeToFit()
var doneButton = UIBarButtonItem(title: "Done", style: .bordered, target: self, action: "inputToolbarDonePressed")
var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
var nextButton = UIBarButtonItem(image: UIImage(named: "keyboardPreviousButton"), style: .bordered, target: self, action: "keyboardNextButton")
nextButton.width = 50.0
var previousButton = UIBarButtonItem(image: UIImage(named: "keyboardNextButton"), style: .Bordered, target: self, action: "keyboardPreviousButton")
toolbar.setItems([fixedSpaceButton, nextButton, fixedSpaceButton, previousButton, flexibleSpaceButton, doneButton], animated: false)
toolbar.userInteractionEnabled = true
return toolbar
}()
UITextFieldDelegate
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
textField.inputAccessoryView = inputToolbar
return true
}
ここでの提案は、「車輪を再発明しないこと」です。
Prev
sを切り替えるためにキーボード上にNext
およびUITextView
ボタンを配置することは非常に一般的であるため、すぐに使用できる多くの優れた実装を見つけることができます。
たとえば、チェックアウト BSKeyboardControl などです。
ポッドを試すこともできます ITextField-Navigation :
pod 'UITextField-Navigation'
2つの遅延読み込みプロパティnextTextField
とpreviousTextField
を任意のUITextFieldに追加します。必要なのは、nextTextField
をインターフェイスビルダーで指定するか、プログラムで指定することだけで、ツールバーがキーボードに追加されます。
プログラム的に:
import UITextField_Navigation
let textField1 = UITextField()
let textField2 = UITextField()
textField1.nextTextField = textField2
assert(textField2 == textField1.nextTextField)
assert(textField1 == textField2.previousTextField)
Interface Builderで:
Swift 3.用に更新
lazy var inputToolbar: UIToolbar = {
var toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.isTranslucent = true
toolbar.sizeToFit()
var doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ContactViewController.inputToolbarDonePressed))
var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
var nextButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(ContactViewController.keyboardNextButton))
var previousButton = UIBarButtonItem(title: "Previous", style: .plain, target: self, action: #selector(ContactViewController.keyboardPreviousButton))
toolbar.setItems([fixedSpaceButton, previousButton, fixedSpaceButton, nextButton, flexibleSpaceButton, doneButton], animated: false)
toolbar.isUserInteractionEnabled = true
return toolbar
}()
その後:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textField.inputAccessoryView = inputToolbar
return true
}
Thange "ContactViewController"をView Controllerの名前に変更することを忘れないでください。
これを試して :-
- (void)viewDidLoad
{
[super viewDidLoad];
[self.topText becomeFirstResponder];
}
- (UIToolbar *)keyboardToolBar {
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];
UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]];
[segControl setSegmentedControlStyle:UISegmentedControlStyleBar];
segControl.momentary = YES;
segControl.highlighted = YES;
[segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)];
[segControl setEnabled:NO forSegmentAtIndex:0];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:segControl];
NSArray *itemsArray = @[nextButton];
[toolbar setItems:itemsArray];
int idx = [sender selectedSegmentIndex];
if (idx == 1) {
[sender setEnabled:NO forSegmentAtIndex:1];
}
else {
[sender setEnabled:NO forSegmentAtIndex:0];
}
return toolbar;
}
- (void)changeRow:(id)sender {
int idx = [sender selectedSegmentIndex];
if (idx == 1) {
self.topText.text = @"Top one";
[self.bottomText becomeFirstResponder];
}
else {
self.bottomText.text =@"Bottom one";
[self.topText becomeFirstResponder];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if (!textField.inputAccessoryView) {
textField.inputAccessoryView = [self keyboardToolBar];
}
}
キーボードが変更されるたびに再初期化されるため、他のアイテムを有効にする必要はありません....