beryulog

iOSアプリ/サーバーサイド開発者のメモと雑記

FXFormsの背景色や書体をカスタマイズする

iOSネイティブアプリ内で入力フォームを作るためにFXFormsを使ったんですが、そのカスタマイズに思いの外手間取ったので取り急ぎ採った方法をメモ。

FXFormControllerをオーバーライド

FXFormsは入力欄をUITableCellで表現しているので、tableのdelegate先になっているFXFormControllerのセル生成メソッドをオーバーライドしました。 多分正攻法ではないので、正しい方法をご存知の方がいたら教えて下さい…m(_ _)m

@interface MYFormController : FXFormController

@end

@implementation MYFormController

/**
 * FXFormTextFieldCellの代わりにMYFormTextFieldCellを使うように初期化処理変更
 */
- (instancetype)init
{
    if ((self = [super init]))
    {
        self.cellClassesForFieldTypes = [@{FXFormFieldTypeDefault: [FXFormBaseCell class],
                                       FXFormFieldTypeText: [MYFormTextFieldCell class],
                                       FXFormFieldTypeLongText: [FXFormTextViewCell class],
                                       FXFormFieldTypeURL: [MYFormTextFieldCell class],
                                       FXFormFieldTypeEmail: [MYFormTextFieldCell class],
                                       FXFormFieldTypePassword: [MYFormTextFieldCell class],
                                       FXFormFieldTypeNumber: [MYFormTextFieldCell class],
                                       FXFormFieldTypeFloat: [MYFormTextFieldCell class],
                                       FXFormFieldTypeInteger: [MYFormTextFieldCell class],
                                       FXFormFieldTypeBoolean: [FXFormSwitchCell class],
                                       FXFormFieldTypeDate: [FXFormDatePickerCell class],
                                       FXFormFieldTypeTime: [FXFormDatePickerCell class],
                                       FXFormFieldTypeDateTime: [FXFormDatePickerCell class],
                                       FXFormFieldTypeImage: [FXFormImagePickerCell class]} mutableCopy];
    }
    return self;
}

/**
 * セルの見た目調節
 */
- (UITableViewCell *)tableView:(__unused UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    
    // 背景色変更
    [cell setBackgroundColor:[UIColor blackColor]];
    
    return cell;
}

@end

FXFormTextFieldCellをオーバーライド

入力欄にフォーカスした時、キーボードの上に閉じるボタンが欲しかったので、入力欄を管理しているFXFormTextFieldCellをオーバーライドしました。 また、標準だとUIReturnKeyNextとUIReturnKeyDoneしか対応していなかったので、UIReturnKeySendにも対応できるように拡張しました。

@interface MYFormTextFieldCell : FXFormTextFieldCell

@end

@implementation MYFormTextFieldCell

- (void)setUp
{
    [super setUp];

    // キーボードに閉じるボタンを追加
    UIView *keyboardActionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 40)];
    [keyboardActionView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1]];
    UIButton *btnClose = [UIButton buttonWithType:UIButtonTypeSystem];
    [btnClose setFrame:CGRectMake(10, 10, 100, 20)];
    [btnClose setTitle:@"閉じる" forState:UIControlStateNormal];
    [btnClose setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [btnClose addTarget:self
                 action:@selector(btnCloseClickHandler:)
       forControlEvents:UIControlEventTouchUpInside];
    [keyboardActionView addSubview:btnClose];
    [self.textField setInputAccessoryView:keyboardActionView];
}

/**
 * キーボードのキャンセルボタンのイベントハンドラ
 */
- (void)btnCloseClickHandler:(UIButton *)sender
{
    // キーボードを隠す
    [self.textField resignFirstResponder];
}

/**
 * キーボードのエンターキーのイベントハンドラ
 */
- (BOOL)textFieldShouldReturn:(__unused UITextField *)textField
{
    if (self.textField.returnKeyType == UIReturnKeyNext)
    {
        // Nextボタン→次の入力項目へフォーカス移動
        [[self nextCell] becomeFirstResponder];
    } else if (self.textField.returnKeyType == UIReturnKeySend) {
        // Sendボタン→フォーカスを外す & 今表示中のViewControllerの送信メソッドを呼ぶ
        [self.textField resignFirstResponder];
        AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
        UINavigationController *navigationController = (UINavigationController *)delegate.window.rootViewController;
        id<MYFormSendProtocol> vc = (id<MYFormSendProtocol>)[navigationController topViewController];
        [vc submitForm];
    } else {
        // それ以外→フォーカスを外す
        [self.textField resignFirstResponder];
    }
    return NO;
}

- (void)update
{
    [super update];

    [self.textField setTextColor:[UIColor whiteColor]];
    self.textField.attributedPlaceholder =
        [[NSAttributedString alloc] initWithString:[self.field.placeholder fieldDescription]
                                        attributes:@{ NSForegroundColorAttributeName:[UIColor whiteColor] }];
}

@end

これでなんとかやりたい事が実現できました。 ゴリ押し感がやばい。。