iOS开发中尝试下超级表单页面和浮动TextFiled的组合,只需要你平时的1/10时间

最近开发中做了很多表单页面,各种UITextField,各种风格,用原生的写,确实写的还不错,但是每次都要花一天时间去调试,效果还是可以的,最近在github上逛,看到了个宇宙第一的表单组件,据说能带你飞,人家是这么宣传的......

XLForm is the most flexible and powerful iOS library to create dynamic table-view forms. The goal of the library is to get the same power of hand-made forms butspending 1/10 of the time.

XLForm provides a very powerful DSL (Domain Specific Language) used to create a form. It keeps track of this specification on runtime,updating the UI on the fly.


看到没,人家要带你飞啊,老司机带上我啊,赶紧写个Demo压压惊

先看图



来看看人家自己封装好的集中强大的表单cell

#import "XLForm.h"
// JVFloatLabeledTextField 普通的文本输入框,自带浮动动画
NSString *const XLFormRowDescriptorTypeText = @"text";
// add的时候展示名字的 JVFloatLabeledTextField
NSString *const XLFormRowDescriptorTypeName = @"name";
// 填写URL的cell
NSString *const XLFormRowDescriptorTypeURL = @"url";
NSString *const XLFormRowDescriptorTypeEmail = @"email";
NSString *const XLFormRowDescriptorTypePassword = @"password";
NSString *const XLFormRowDescriptorTypeNumber = @"number";
NSString *const XLFormRowDescriptorTypePhone = @"phone";
NSString *const XLFormRowDescriptorTypeTwitter = @"twitter";
NSString *const XLFormRowDescriptorTypeAccount = @"account";
NSString *const XLFormRowDescriptorTypeInteger = @"integer";
// 选择更换头像图片的cell
NSString *const XLFormRowDescriptorTypeImage = @"image";
NSString *const XLFormRowDescriptorTypeDecimal = @"decimal";
// JVFloat对应的textView的cell
NSString *const XLFormRowDescriptorTypeTextView = @"textView";
NSString *const XLFormRowDescriptorTypeZipCode = @"zipCode";
// 非常普通的点击push选择
NSString *const XLFormRowDescriptorTypeSelectorPush = @"selectorPush";
NSString *const XLFormRowDescriptorTypeSelectorPopover = @"selectorPopover";
NSString *const XLFormRowDescriptorTypeSelectorActionSheet = @"selectorActionSheet";
NSString *const XLFormRowDescriptorTypeSelectorAlertView = @"selectorAlertView";
NSString *const XLFormRowDescriptorTypeSelectorPickerView = @"selectorPickerView";
NSString *const XLFormRowDescriptorTypeSelectorPickerViewInline = @"selectorPickerViewInline";
NSString *const XLFormRowDescriptorTypeMultipleSelector = @"multipleSelector";
NSString *const XLFormRowDescriptorTypeMultipleSelectorPopover = @"multipleSelectorPopover";
NSString *const XLFormRowDescriptorTypeSelectorLeftRight = @"selectorLeftRight";
// 三段选择
NSString *const XLFormRowDescriptorTypeSelectorSegmentedControl = @"selectorSegmentedControl";
// date 月 日 年  (内嵌)
NSString *const XLFormRowDescriptorTypeDateInline = @"dateInline";
// 日期picker选择器内嵌 dateTime更详细  星期 月 日 小时  分(内嵌)
NSString *const XLFormRowDescriptorTypeDateTimeInline = @"datetimeInline";
// date 小时 分 AM/PM(内嵌)
NSString *const XLFormRowDescriptorTypeTimeInline = @"timeInline";
// 计时器,选择hh mm(内嵌)
NSString *const XLFormRowDescriptorTypeCountDownTimerInline = @"countDownTimerInline";
// 月 日 年 sheet
NSString *const XLFormRowDescriptorTypeDate = @"date";
// 最详细的dateTime sheet
NSString *const XLFormRowDescriptorTypeDateTime = @"datetime";
// 小时 分 AM/PM  sheet
NSString *const XLFormRowDescriptorTypeTime = @"time";
// 计时器  底部弹出来的
NSString *const XLFormRowDescriptorTypeCountDownTimer = @"countDownTimer";
// 直接展示一大坨datePicker
NSString *const XLFormRowDescriptorTypeDatePicker = @"datePicker";
NSString *const XLFormRowDescriptorTypePicker = @"picker";
// slider
NSString *const XLFormRowDescriptorTypeSlider = @"slider";
// 展示选中打钩的cell
NSString *const XLFormRowDescriptorTypeBooleanCheck = @"booleanCheck";
// 自带右边switch开关 
NSString *const XLFormRowDescriptorTypeBooleanSwitch = @"booleanSwitch";
// button的cell  各种button位置需求
NSString *const XLFormRowDescriptorTypeButton = @"button";
// 简单的右侧描述信息的cell
NSString *const XLFormRowDescriptorTypeInfo = @"info";
// 展示segment count计数
NSString *const XLFormRowDescriptorTypeStepCounter = @"stepCounter";

好多是吧,咱们直接拿来用就好了,类似于UITableView注册的cellID


你以为这就完了???!!!!

老外的库怎么能少了自定义功能呢,没有这个功能,那么这个库和咸鱼又有什么区别呢??!!



第一步:创建控制器(继承XLFormViewController)

分析:

这里init方法里面有三个值

XLFormDescriptor   表单

XLFormSectionDescriptor   section

XLFormRowDescriptor  row

咱们挨个创建,并且add到对应的section就可以了,最后记得带上一句self.form = form

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        [self initializeForm];
    }
    return self;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initializeForm];
    }
    return self;
}
// 初始化表单
- (void)initializeForm
{
    // 表单对象
    XLFormDescriptor *form;
    // 表单Section对象
    XLFormSectionDescriptor *section;
    // 表单Row对象
    XLFormRowDescriptor *row;
    
    // 初始化form 顺便带个title
    form = [XLFormDescriptor formDescriptorWithTitle:@"超级表单"];
    
    // 第一个Section 没有参数的
    section = [XLFormSectionDescriptor formSection];
    [form addFormSection:section];
    
    // 第一个就要自定义 车牌号 自定义cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"first" rowType:XLFormRowDescriporTypeCar title:@"车牌号"];
    row.required = YES;
    row.value = @{@"country":@"浙",@"number":@"123456"};
    [section addFormRow:row];
    
    
    // 第二段
    section = [XLFormSectionDescriptor formSection];
    [form addFormSection:section];
    
    // 第二个发动机号 自带的Cell
    // Name
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"second" rowType:XLFormRowDescriptorTypeText title:@"发动机号"];
    row.required = YES;
    // font
    [row.cellConfig setObject:[UIFont boldSystemFontOfSize:16] forKey:@"textLabel.font"];
    // font
    [row.cellConfig setObject:[UIFont boldSystemFontOfSize:16] forKey:@"textField.font"];
    // alignment
    [row.cellConfig setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
    [section addFormRow:row];
    
    section = [XLFormSectionDescriptor formSection];
    [form addFormSection:section];
    
    // 第三个底部Sheet Picker 自带Cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"third" rowType:XLFormRowDescriptorTypeSelectorPickerView title:@"车型"];
    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"奥迪A4"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"丰田SUV"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"凯迪拉克"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"奔驰"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"BMW"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(5) displayText:@"雷克萨斯"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(6) displayText:@"马自达"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(7) displayText:@"本田"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(8) displayText:@"特斯拉"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(9) displayText:@"福特"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(10) displayText:@"雷诺"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(11) displayText:@"法拉利"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(12) displayText:@"宾利"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(13) displayText:@"玛莎拉蒂"]
                            ];
//    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"];
    [section addFormRow:row];
    
    // 第四个内嵌Picker 自带Cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"four" rowType:XLFormRowDescriptorTypeSelectorPickerViewInline title:@"车长"];
    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"1M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"2M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"3M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"4M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"5M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(5) displayText:@"6M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(6) displayText:@"7M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(7) displayText:@"8M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(8) displayText:@"9M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(9) displayText:@"10M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(10) displayText:@"11M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(11) displayText:@"12M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(12) displayText:@"13M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(13) displayText:@"14M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(14) displayText:@"15M"],
                            ];
    [section addFormRow:row];
    
    // 第五个浮动TF 自带cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"five" rowType:XLFormRowDescriptorTypeFloatLabeledTextField111 title:@"请输入体积大小"];
    [section addFormRow:row];
    
    // 第六个测试下  自定义cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"six" rowType:XLFormRowDescriporTypeFloat title:@"请输入面积大小"];
    row.value = @{@"left":@"面积(m³)",@"right":@""};
    [section addFormRow:row];
    
    // 第七个评分 自带cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"seven" rowType:XLFormRowDescriptorTypeRate title:@"First Rating"];
    row.value = @(3);
    [section addFormRow:row];
    
    
    // 测试新增栏目  自带cell
    section = [XLFormSectionDescriptor formSectionWithTitle:@"XLFormSectionInsertModeButton With Inline Cells"
                                             sectionOptions:XLFormSectionOptionCanInsert
                                          sectionInsertMode:XLFormSectionInsertModeButton];
    [form addFormSection:section];
    row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeDateInline];
    row.value = [NSDate new];
    row.title = @"新增picker栏测试";
    section.multivaluedRowTemplate = row;
    
    
    
    
    section = [XLFormSectionDescriptor formSection];
    [form addFormSection:section];
    
    
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"eight" rowType:XLFormRowDescriptorTypeUpload];
    [section addFormRow:row];
    
    
    self.form = form;
    
}

第二步:用它自带的表单cell来加载(简单粗暴)

举个栗子(内嵌的pickerView)

 row = [XLFormRowDescriptor formRowDescriptorWithTag:@"four" rowType:XLFormRowDescriptorTypeSelectorPickerViewInline title:@"车长"];
    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"1M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"2M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"3M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"4M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"5M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(5) displayText:@"6M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(6) displayText:@"7M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(7) displayText:@"8M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(8) displayText:@"9M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(9) displayText:@"10M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(10) displayText:@"11M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(11) displayText:@"12M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(12) displayText:@"13M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(13) displayText:@"14M"],
                            [XLFormOptionsObject formOptionsObjectWithValue:@(14) displayText:@"15M"],
                            ];
    [section addFormRow:row];


非常的简单快速,初始化Row的时候第一个参数是该cell的identify值,方便后续点击事件的追溯,第二个参数就是

form表单中注册的一个ID,最后的title可有可无,用来初始化赋值,然后直接ADD到对应的section就可以了


每个Row的对象XLFormRowDescriptor内置了很多属性,可以点进去看看需要什么,不在这里啰嗦了



第三步:自定义Cell到form表单中,有了它,你就能应付全世界的需求

再举个栗子....


我们介绍上面那栏,打分的不介绍了,需要的自己去下载Demo(文章结尾有地址)

其实在Controller中的代码还是一样简单

// 第六个测试下  自定义cell
    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"six" rowType:XLFormRowDescriporTypeFloat title:@"请输入面积大小"];
    row.value = @{@"left":@"面积(m³)",@"right":@""};
    [section addFormRow:row];


但是Cell的实现就需要认真看看了

首先XIB来个cell(记得继承XLFormBaseCell,而且我们要放一个浮动的TextField进去


自定义Cell我们必须重写三个方法

1.load (注册自定义cell)

2.configure (初始化配置)

3.update (更新数据其实就是更新rowDescription对象的Value字段,再VC里面代理刷新cell)

// 内部直接赋值
NSString * const XLFormRowDescriporTypeFloat = @"XLFormRowDescriporTypeFloat";

@interface MKJFloatTextFieldCell () <UITextFieldDelegate>

@end

@implementation MKJFloatTextFieldCell

// 在主表单中注册对应的cell以及对应的ID
+(void)load
{
    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:NSStringFromClass([MKJFloatTextFieldCell class]) forKey:XLFormRowDescriporTypeFloat];
}

// 这个方法是用来设置属性的 必须重写  类似于初始化的属性不变的属性进行预先配置
- (void)configure
{
    [super configure];
    
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    self.leftLabel.layer.borderColor = [UIColor yellowColor].CGColor;
    self.leftLabel.layer.borderWidth = 1.0f;
    self.textField.delegate = self;
    self.textField.font = [UIFont boldSystemFontOfSize:16];
    self.textField.floatingLabel.font = [UIFont boldSystemFontOfSize:11];
    self.textField.clearButtonMode = UITextFieldViewModeWhileEditing;
    self.textField.floatingLabelTextColor = [UIColor lightGrayColor];
    self.textField.floatingLabelActiveTextColor = [UIColor redColor];
    
}
// 这个方法是用来进行更新的,外面给唯一的字段Value设定值就好了 通过self.rowDescriptor.value的值变化来进行更新
- (void)update
{
    [super update];
    NSDictionary *value = self.rowDescriptor.value;
    self.leftLabel.text = [value objectForKey:@"left"];
    self.textField.text = [value objectForKey:@"right"];
    self.textField.attributedPlaceholder =
    [[NSAttributedString alloc] initWithString:self.rowDescriptor.title
                                    attributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]}];
    self.textField.floatingLabel.text = @"快点输入面积大小";
}

那么肯定有疑问?他是如何记录TextField更新数据的?例如,其他cell,他是如何把数据刷上去的?最后提交表单

整个表单的总数据是怎么来的

1.如何更新?(剩下的疑问看最后的几步)

这里XLFormRowDescription对象是有个id类型的value字段的,我们内部控件的事件更新了,我们只

负责更新都应的value字段(内部结构也是自己定义的数组或者字典或者其他)

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self textFieldDidChange:textField];
    [self.formViewController textFieldDidEndEditing:textField];
}

#pragma mark - Helpers

- (void)textFieldDidChange:(UITextField *)textField
{
    NSMutableDictionary *value = [self.rowDescriptor.value mutableCopy];
    if (self.textField == textField) {
        if ([self.textField.text length] > 0) {
            
            [value setObject:self.textField.text forKey:@"right"];
            
        } else {
            
            [value setObject:@"" forKey:@"right"];
            
        }
    }
    self.rowDescriptor.value = value;
}

这里已经更新了form表单中对应cell对应的value,但是这样貌似根本没有刷新嘛,像现

在这样的TextField就没事,如果和上图第一个cell那种的选择城市,需要更新cell,那

么,我们还需要在ViewController里面进行update一下


第四步:有些特定事件,需要在VC里面进行判断更新或者移除或者增加

// 每个cell内部的参数属性更改了就会调用这个方法,我们再次更新的话就会调用cell里面update的方法进行重绘
- (void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue
{
    // 咱们这里统一调用更新
    [super formRowDescriptorValueHasChanged:formRow oldValue:oldValue newValue:newValue];
    [self updateFormRow:formRow];
    
    
    // 以下就是一些典型的tag判断,根据不同的cell,remove 或 update进行更改
//    if ([rowDescriptor.tag isEqualToString:@"first"]){
//
//    }
//    else if ([rowDescriptor.tag isEqualToString:@"second"]){
//
//        [self updateFormRow:startDateDescriptor];
//        [self updateFormRow:endDateDescriptor];
//    }
//    else if ([rowDescriptor.tag isEqualToString:@"third"]){
//        
//            [self updateFormRow:endDateDescriptor];
//        
//    }
//    else if ([rowDescriptor.tag isEqualToString:@"这里填写的就是我们注册的ID"]){
//        
//    }
    
}



第五步:表单填完了,无论自定义还是自带的,都要搜集填写的

数据

XLFormViewController的代理方法

-(NSDictionary *)formValues;

有了它我们就能拿到所有的表单数据

</pre><pre name="code" class="objc">- (IBAction)clickDone:(id)sender {
    
    NSDictionary *dict = [self formValues];
    NSLog(@"表单中所有的字典值%@",dict);
}

2016-09-09 14:23:54.403 MKJForm[3694:150388]表单中所有的字典值{

    eight = "<null>";

    first =     {

        country = "\U5e7f";

        number = "";

    };

    five = 2121212;

    four = "<XLFormOptionsObject: 0x7ff5cb917ea0>";

    second = 12121;

    seven = 1;

    six =     {

        left = "\U9762\U79ef(m\U00b3)";

        right = 121212;

    };

    third = "<XLFormOptionsObject: 0x7ff5cb91f080>";

}



最后检测下内存泄漏,打印了就OK

- (void)dealloc
{
    NSLog(@"%s-->dealloc",object_getClassName(self));
}


写完Demo,回头看确实非常方便,什么键盘高度,事件判断,tableView都不需要我们管理,关键是能自定义,一般有这个功能的组件都有点强的,用起来简直能飞

.



Demo地址:点击打开Demo链接

对了,看到这里的小伙伴,给大家分享个如何给Github上的README添加gif,我也是才

知道,赶紧记录下分享给大伙

点击打开链接(在末尾)



  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值