先上图看看这是不是你想要的
本方法依赖 yytext Masonry 需要pod引入
pod 'Masonry'
pod 'YYText'
我们后台给的数据格式是 ##### “这是第一个填空{2},这是第三个填空{3}这个填空比较多{7}数据库来啦”。其中 {2}表示有两个空格要填 ,{3}表示有三个空格要填
首先定义一个YYLabel,用于显示答题的题目,并且后续会包含填空的空格
self.contentLabel = [[YYLabel alloc] initWithFrame:CGRectMake(10, 80, CZTVSCREEN_WIDTH - 10*2, 50)];
self.contentLabel.numberOfLines = 0;
[self.view addSubview:self.contentLabel];
[self.contentLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@40);
make.left.equalTo(@10);
make.right.mas_equalTo(self.view).offset(-10);
make.bottom.equalTo(self.view).offset(-200);
}];
其次,我们通过正则匹配的每一个{x},然后计算出需要的总填空组数和每一组的填空的空格数'
#pragma 特定字符串替换为UIButton
-(void)replaceStrWithImageAllString:(NSString *)titleString {
self.allGroupArr = [NSMutableArray arrayWithCapacity:0];
NSMutableAttributedString *alertAttributedString = [[NSMutableAttributedString alloc] initWithString:titleString];
NSString *regexStr =@"\\{[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\}";//正则匹配,获取{X},表示数字
NSError *error =nil;
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:&error];
if(!re) { //没有匹配到{x}
return;
}
// 正则匹配后的数组
NSArray *resultArray = [re matchesInString:titleString options:0 range:NSMakeRange(0, titleString.length)];
NSInteger i = 0; //
//根据匹配范围来用UITextField进行相应的替换
for(NSTextCheckingResult *match in resultArray) {
//获取数组元素中得到range
NSRange range = [match range];
//获取原字符串中对应的值
NSString *subStr = [titleString substringWithRange:range]; //匹配到的{x} x表示数字
// NSLog(@" 获取原字符串中对应的值 === %@",subStr);
NSDictionary *rangDic = [self getRangeStr:[alertAttributedString string] findText:subStr];
if (rangDic) {
NSInteger subLocation = [[rangDic objectForKey:@"location"] integerValue]; //初始位置
NSInteger lengthNum = [[rangDic objectForKey:@"length"] integerValue];//需要替换的长度
NSInteger orignLengthNum = [[rangDic objectForKey:@"orignLength"] integerValue]; //原始的长度
NSMutableAttributedString *tempStr = [[NSMutableAttributedString alloc] init];
NSMutableArray *tempGroupArray = [NSMutableArray arrayWithCapacity:0];
for (NSInteger j = 0; j < lengthNum ; j++) {
UIButton *spaceBtn = [UIButton buttonWithType:UIButtonTypeCustom];
spaceBtn.frame = CGRectMake(5, 0, 27, 27);
spaceBtn.tag = j + 100 + i * 100;
spaceBtn.layer.borderColor = [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1].CGColor;
spaceBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
spaceBtn.backgroundColor = [UIColor colorWithRed:243/255.0 green:244/255.0 blue:246/255.0 alpha:1];
[spaceBtn setTitleColor:[UIColor colorWithRed:78/255.0 green:200/255.0 blue:109/255.0 alpha:1] forState:UIControlStateNormal];
[spaceBtn addTarget:self action:@selector(spaceBtnAction:) forControlEvents:UIControlEventTouchUpInside];
[tempGroupArray addObject:spaceBtn];
NSMutableAttributedString *imageText = [NSMutableAttributedString yy_attachmentStringWithContent:spaceBtn contentMode:UIViewContentModeScaleAspectFit attachmentSize:CGSizeMake(37, 27) alignToFont:[UIFont systemFontOfSize:16] alignment:YYTextVerticalAlignmentCenter]; // 图片转化为特殊字符
[tempStr appendAttributedString:imageText];
}
[self.allGroupArr addObject:tempGroupArray];
[alertAttributedString replaceCharactersInRange:NSMakeRange(subLocation , orignLengthNum) withAttributedString:tempStr];
}
i +=1;
}
NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
paraStyle.lineSpacing = 8; //设置行间距
[alertAttributedString addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],
NSForegroundColorAttributeName:[UIColor blackColor],
NSParagraphStyleAttributeName:paraStyle
} range:NSMakeRange(0, alertAttributedString.length)];
self.contentLabel.attributedText = alertAttributedString;
}
#pragma mark - 查找子字符串在父字符串的所有位置,需要的空格数量
- (NSDictionary *)getRangeStr:(NSString *)text findText:(NSString *)findText {
if (findText == nil && [findText isEqualToString:@""]) {
return nil;
}
NSString *tempfindText = [findText stringByReplacingOccurrencesOfString:@"{" withString:@""];
tempfindText = [tempfindText stringByReplacingOccurrencesOfString:@"}" withString:@""];
NSInteger lengthNumber = [tempfindText integerValue];
NSRange rang = [text rangeOfString:findText]; //获取第一次出现的range
if (rang.location != NSNotFound && rang.length != 0) {
NSDictionary *rangDic = @{@"location":@(rang.location), @"length":@(lengthNumber), @"orignLength":@(findText.length)};
return rangDic;
}
return nil;
}
#pragma mark - 点击每个button
- (void)spaceBtnAction:(UIButton *)sender {
// textField第一响应
[_textField becomeFirstResponder];
// NSLog(@" 当前选中按钮的tag值 === %ld", (long)sender.tag);
_currentGroupTag = floor(sender.tag / 100) - 1;
// NSLog(@" 向下取整后的分组tag值 === %ld", (long)_currentGroupTag);
[self changeBtnUnselectedState];
[self changeBtnSelectedState];
}
// 改变选中分组内按钮的未选中状态
- (void)changeBtnUnselectedState {
// 把其他的置spaceBtn为未选中状态
for (NSInteger i = 0 ; i < self.allGroupArr.count; i++ ) {
if (i != _currentGroupTag) {
NSMutableArray *unselectedGroupArray = [self.allGroupArr objectAtIndex:i];
for (UIButton *unselectedBtn in unselectedGroupArray) {
unselectedBtn.layer.borderWidth = 0;
}
}
}
}
以上只是纯展示,重点来了,为了让我们能够编辑每个图片,我是使用了一个textField放在了顶部(后期你们使用的时候,可以把textField背景色,光标,等等设置为透明就行了)
然后我们通过创建多个参数,来设置并单独控制每组空格的输入
- (void)loadTextField {
_textField = [[UITextField alloc] init];
_textField.textColor = [UIColor blackColor];
_textField.delegate = self;
_textField.backgroundColor = UIColor.orangeColor;
[self.view addSubview:_textField];
[_textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@50);
make.left.equalTo(@20);
make.right.mas_equalTo(self.view).offset(-20);
make.height.equalTo(@40);
}];
}
// 改变选中分组内按钮的选中状态
- (void)changeBtnSelectedState {
// 拼接所选分组下,所有已填写内容
_currentGroupWriteStr = @"";
// 当前选中的btn所在分组数组
NSMutableArray *selectedGroupArray = [self.allGroupArr objectAtIndex:_currentGroupTag];
// 赋值所选分组下的所有数量
_currentSeleectedGroupNumber = selectedGroupArray.count;
// 遍历改变按钮选中状态
for (NSInteger i = 0; i < selectedGroupArray.count; i++) {
UIButton *selectedBtn = [selectedGroupArray objectAtIndex:i];
if (selectedBtn.currentTitle.length == 0) {
selectedBtn.layer.borderWidth = 1;
break;
} else {
_currentGroupWriteStr = [NSString stringWithFormat:@"%@%@",_currentGroupWriteStr,selectedBtn.currentTitle];
if (i == selectedGroupArray.count - 1) { //最后一个
selectedBtn.layer.borderWidth = 1;
} else {
selectedBtn.layer.borderWidth = 0;
}
}
}
_textField.text = _currentGroupWriteStr;
}
#pragma mark - UITextFieldDelegate
/**
正在编辑的文字:textField.text
将要改变的字符范围:range.length 输入时或直接点击文字选择栏现有文字时:0 编辑后确认时:非0
将要替换成的字符串:string
*/
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// NSLog(@" 正在编辑的文字 ===== %@",textField.text);
// NSLog(@" 将要改变的字符范围 ===== %ld",range.length);
// NSLog(@" 将要替换成的字符串 ===== %@",string);
// NSLog(@" 将要替换成的字符串的字符长度 ===== %ld",string.length);
// string.length: 0-正在删除
if (string.length == 0) { //正在删除
if (_textField.text.length != 0 && _currentGroupWriteStr.length == _textField.text.length) { //删除字符串
_currentGroupWriteStr = [_currentGroupWriteStr substringWithRange:NSMakeRange(0, _currentGroupWriteStr.length - 1)];
//给btn赋值
[self textFieldDeleteBtnTitle];
}
return YES;
}
if (range.length != 0) { //编辑后确认
BOOL isChange = [self textFieldShouldChangeWithStr:string];
return isChange;
} else {
// NSLog(@"输入的类型:%@",);
unichar commitChar = [string characterAtIndex:0];
if ((commitChar>10122)&&(commitChar<10131)) {
// NSLog(@"这里是苹果输入法九宫格");
//中文编辑过程的特殊字符➎ 此处代码不要删除
// 2 10123 3 10124 4 10125 5 10126 610127 7 10128 8 10129 9 10130
} else { //全键盘
// NSLog(@"这里是苹果输入法全键盘");
if ([[_textField.textInputMode primaryLanguage] isEqual:@"zh-Hans"]) { //中文
if ([self isThirdPartyKeyboard]) { //第三方输入法
// NSLog(@"第三方输入法");
BOOL isChange = [self textFieldShouldChangeWithStr:string];
return isChange;
} else { //苹果输入法不填充
// NSLog(@"苹果输入法");
return YES;
}
} else {
BOOL isChange = [self textFieldShouldChangeWithStr:string];
return isChange;
}
}
}
return YES;
}
#pragma mark -判断当前输入法是否你是非苹果输入法
- (BOOL)isThirdPartyKeyboard {
UITextInputMode *currentInputMode = [[UIApplication sharedApplication] textInputMode];
NSString *currentInputModeClass = NSStringFromClass([currentInputMode class]);
if ([currentInputModeClass isEqualToString:@"UIKeyboardExtensionInputMode"]) {
return YES;
}
return NO;
}
- (BOOL)textFieldShouldChangeWithStr:(NSString *)string {
//当前编辑文字大于选中分组的数量
//且大于已填写数量
if ((_textField.text.length + string.length) > _currentSeleectedGroupNumber) {
// 已填写 < 分组内的空格
if (_currentGroupWriteStr.length < _currentSeleectedGroupNumber) {
NSString *contentStr = [NSString stringWithFormat:@"%@%@",_currentGroupWriteStr,string];
if (contentStr.length > _currentSeleectedGroupNumber) {
_currentGroupWriteStr = [contentStr substringWithRange:NSMakeRange(0, _currentSeleectedGroupNumber)];
} else {
_currentGroupWriteStr = contentStr;
}
_textField.text = _currentGroupWriteStr;
//给btn赋值
[self textFieldChangeBtnTitle];
}
return NO;
} else {
_currentGroupWriteStr = [NSString stringWithFormat:@"%@%@",_currentGroupWriteStr,string];
//给btn赋值
[self textFieldChangeBtnTitle];
}
return YES;
}
// textField输入改变按钮状态
- (void)textFieldChangeBtnTitle {
// 当前选中的btn所在分组数组
NSMutableArray *selectedGroupArray = [self.allGroupArr objectAtIndex:_currentGroupTag];
// 遍历改变按钮选中状态
for (NSInteger i = 0; i < selectedGroupArray.count; i++) {
UIButton *selectedBtn = [selectedGroupArray objectAtIndex:i];
if (i < _currentGroupWriteStr.length) {
NSString *titleStr = [_currentGroupWriteStr substringWithRange:NSMakeRange(i, 1)];
[selectedBtn setTitle:titleStr forState:UIControlStateNormal];
[selectedBtn setTitleColor:[UIColor colorWithRed:78/255.0 green:200/255.0 blue:109/255.0 alpha:1] forState:UIControlStateNormal];
}
if (selectedBtn.currentTitle.length == 0) {
selectedBtn.layer.borderWidth = 1;
break;
} else {
if (i == selectedGroupArray.count - 1) { //最后一个
selectedBtn.layer.borderWidth = 1;
} else {
selectedBtn.layer.borderWidth = 0;
}
}
}
}
// textField删除改变按钮状态
- (void)textFieldDeleteBtnTitle {
// 当前选中的btn所在分组数组
NSMutableArray *selectedGroupArray = [self.allGroupArr objectAtIndex:_currentGroupTag];
// 遍历改变按钮选中状态
for (NSInteger i = 0; i < selectedGroupArray.count; i++) {
UIButton *selectedBtn = [selectedGroupArray objectAtIndex:i];
if (i == _currentGroupWriteStr.length) {
[selectedBtn setTitle:@"" forState:UIControlStateNormal];
selectedBtn.layer.borderWidth = 1;
} else {
selectedBtn.layer.borderWidth = 0;
}
}
}
最后来个demo链接