我的要求也是一样的,但我用本地代码解决了它,使用UILabel & UIView,所有这些都通过实用的循环来完成。考虑下面的文字。
曾几何那里_____ 一个叫达摩克利斯的男人。他的一个朋友最终成为了一个小城市的统治者。达摩克里斯认为,'我的朋友多么幸运____。他____ 现在是一个统治者。他必须____ 过得很愉快。
其中每件作品被视为UILabel
被视为UIView
的空白空间。正确的选项在如下所示的有序列表中。
(lldb) po self.card.questionDataModel.fillAnswers
<__NSArrayI 0x6000008798c0>(
lived,
became,
is,
is,
must be having
)
查看代码。
这种方法使得空的空间整个用户界面及其选项
- (void)prepareUIForFillInBlankQuestionType {
self.totalOptionCount = self.card.questionDataModel.fillAnswers.count;
CGFloat leading = 8;
CGFloat trailing = 8;
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.question] == NO) {
NSAttributedString* titleAttributedString = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.question];
NSString* titleString = titleAttributedString.string;
// Holds all blank UIView (empty spaces)
NSMutableArray* blankViewContainerList = [NSMutableArray new];
// Full string will be separate by spaces so that each work can for single instance of UILabel
NSArray* blankSpaceSeperatedList = [titleString componentsSeparatedByString:@" "];
CGFloat fillViewWidth = CGRectGetWidth(self.fillBlankContainerView.frame);
CGFloat labelX = 8;
CGFloat labelY = 8;
CGFloat labelHeight = 25;
NSInteger underscoreIndex = 0;
for (NSString* text in blankSpaceSeperatedList) {
CGFloat fillContainerWidth = (fillViewWidth - (trailing + leading));
// inputs NSString instance, will return back its UILabel for all words in a sentence
UILabel* textLabel = [self labelFromText:text];
if ((labelX + textLabel.frame.size.width) < fillContainerWidth) {
if ([text containsString:@"__"]) {
CGFloat answerWidth = CGRectGetWidth(self.fillBlankContainerView.frame) * FILL_FRAME_RATIO; // 0.4
UIView* blankView = [[UIView alloc] initWithFrame:CGRectMake(labelX,
labelY,
answerWidth,
labelHeight)];
CALayer* bottomLayer = [CALayer layer];
[bottomLayer setFrame:CGRectMake(0, labelHeight - 1, CGRectGetWidth(blankView.frame), 1)];
[bottomLayer setBackgroundColor:[UIColor whiteColor].CGColor];
[blankView.layer addSublayer:bottomLayer];
[blankView setTag:(600 + underscoreIndex)];
underscoreIndex++;
if (labelX + CGRectGetWidth(blankView.frame) >= fillContainerWidth) {
labelX = leading;
labelY += labelHeight;
[blankView setFrame:CGRectMake(labelX, labelY, answerWidth, labelHeight)];
}
[self.fillBlankContainerView addSubview:blankView];
[blankViewContainerList addObject:blankView];
labelX += answerWidth;
}
else {
CGRect labelFrame = textLabel.frame;
labelFrame.origin.x = labelX;
labelFrame.origin.y = labelY;
[textLabel setFrame:labelFrame];
[self.fillBlankContainerView addSubview:textLabel];
labelX += textLabel.frame.size.width;
}
}
else{
labelX = leading;
labelY += labelHeight;
if ([text containsString:@"__"]) {
CGFloat answerWidth = CGRectGetWidth(self.fillBlankContainerView.frame) * FILL_FRAME_RATIO;
UIView* blankView = [[UIView alloc] initWithFrame:CGRectMake(labelX,
labelY,
answerWidth,
labelHeight)];
CALayer* bottomLayer = [CALayer layer];
[bottomLayer setFrame:CGRectMake(0, labelHeight - 1, CGRectGetWidth(blankView.frame), 1)];
[bottomLayer setBackgroundColor:[UIColor whiteColor].CGColor];
[blankView.layer addSublayer:bottomLayer];
[blankView setTag:(600 + underscoreIndex)];
underscoreIndex++;
if (labelX + CGRectGetWidth(blankView.frame) >= fillContainerWidth) {
labelX = leading;
labelY += labelHeight;
[blankView setFrame:CGRectMake(labelX, labelY, answerWidth, labelHeight)];
}
[self.fillBlankContainerView addSubview:blankView];
[blankViewContainerList addObject:blankView];
labelX += answerWidth;
}
else {
CGRect labelFrame = textLabel.frame;
labelFrame.origin.x = labelX;
labelFrame.origin.y = labelY;
[textLabel setFrame:labelFrame];
[self.fillBlankContainerView addSubview:textLabel];
labelX += textLabel.frame.size.width;
}
}
}
self.blankViewContaninerList = blankViewContainerList;
// It has all the options which will dragged on empty spaces
NSMutableArray* optionList = [NSMutableArray new];
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.A] == NO) {
NSAttributedString* attributedStringA = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.A];
NSString* optionA = [NSRUtilities trimNewlineCharacterFromString:attributedStringA.string];
[optionList addObject:optionA];
}
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.B] == NO) {
NSAttributedString* attributedStringB = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.B];
NSString* optionB = [NSRUtilities trimNewlineCharacterFromString:attributedStringB.string];
[optionList addObject:optionB];
}
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.C] == NO) {
NSAttributedString* attributedStringC = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.C];
NSString* optionC = [NSRUtilities trimNewlineCharacterFromString:attributedStringC.string];
[optionList addObject:optionC];
}
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.D] == NO) {
NSAttributedString* attributedStringD = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.D];
NSString* optionD = [NSRUtilities trimNewlineCharacterFromString:attributedStringD.string];
[optionList addObject:optionD];
}
if ([NSRUtilities isNilOREmptyString:self.card.questionDataModel.E] == NO) {
NSAttributedString* attributedStringE = [[ConstantTools sharedData] convertHTMLToString:self.card.questionDataModel.E];
NSString* optionE = [NSRUtilities trimNewlineCharacterFromString:attributedStringE.string];
[optionList addObject:optionE];
}
CGFloat optionsYPoint = labelY + 50;
for (NSInteger optionIndex = 0 ; optionIndex < optionList.count ; optionIndex++) {
NSString* option = optionList[optionIndex];
UILabel* optionLabel = [self optionLabelFromText:option index:optionIndex];
if (optionIndex % 2 == 0) {
// Fall out on left side
CGFloat centerPoint = (CGRectGetWidth(self.fillBlankContainerView.frame)/4);
CGFloat optionsCenterPoint = (CGRectGetWidth(optionLabel.frame)/2);
CGFloat x = centerPoint - optionsCenterPoint;
CGFloat y = optionsYPoint;
CGFloat width = CGRectGetWidth(optionLabel.frame);
CGFloat height = 25;
[optionLabel setFrame:CGRectMake(x, y, width, height)];
[self.fillBlankContainerView addSubview:optionLabel];
// struct optionRect
optionLabel.tag = optionIndex;
optionRect[optionIndex].origin = optionLabel.frame.origin;
optionRect[optionIndex].size = optionLabel.frame.size;
optionRect[optionIndex].center = optionLabel.center;
}
else {
// Fall out on right side
CGFloat centerPoint = CGRectGetWidth(self.fillBlankContainerView.frame) -(CGRectGetWidth(self.fillBlankContainerView.frame)/4);
CGFloat optionsCenterPoint = (CGRectGetWidth(optionLabel.frame)/2);
CGFloat x = centerPoint - optionsCenterPoint;
CGFloat y = optionsYPoint;
CGFloat width = CGRectGetWidth(optionLabel.frame);
CGFloat height = 25;
[optionLabel setFrame:CGRectMake(x, y, width, height)];
[self.fillBlankContainerView addSubview:optionLabel];
// struct optionRect
optionLabel.tag = optionIndex;
optionRect[optionIndex].origin = optionLabel.frame.origin;
optionRect[optionIndex].size = optionLabel.frame.size;
optionRect[optionIndex].center = optionLabel.center;
optionsYPoint += 40;
}
}
}
}
这些方法会准备的UILabel出来的NSString
- (UILabel*)labelFromText:(NSString*)text {
UIFont* boldFont = [UIFont boldSystemFontOfSize:15];
NSAttributedString* labelString = [[NSAttributedString alloc ] initWithString:text
attributes:@{NSFontAttributeName:boldFont}];
CGRect cellRect = [labelString boundingRectWithSize:CGSizeMake(MAXFLOAT, 30)
options:NSStringDrawingUsesLineFragmentOrigin context:nil];
CGFloat width = cellRect.size.width + 10;
UILabel* textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 25)];
[textLabel setText:text];
[textLabel setTextColor:[UIColor whiteColor]];
return textLabel;
}
- (UILabel*)optionLabelFromText:(NSString*)text index:(NSInteger)index{
UIFont* regularFont = [UIFont systemFontOfSize:14];
CGFloat width = CGRectGetWidth(self.view.frame) * FILL_FRAME_RATIO; // 0.4;
UILabel* optionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 25)];
[optionLabel setText:text];
[optionLabel setFont:regularFont];
[optionLabel setTextColor:[UIColor whiteColor]];
[optionLabel setTextAlignment:NSTextAlignmentCenter];
[optionLabel setBackgroundColor:[UIColor lightTextColor]];
[optionLabel.layer setBorderColor:[UIColor whiteColor].CGColor];
[optionLabel.layer setBorderWidth:1.0];
[optionLabel.layer setCornerRadius:2.0];
[optionLabel.layer setMasksToBounds:YES];
[optionLabel setUserInteractionEnabled:YES];
UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureForFillInBlank:)];
[optionLabel addGestureRecognizer:panGesture];
return optionLabel;
}
此方法在拖动&拖放功能帮助
- (void)handlePanGestureForFillInBlank:(UIPanGestureRecognizer*)sender{
__block BOOL isDragOnBlank = NO;
NSInteger tag = sender.view.tag;
OptionsFrame senderRect = optionRect[tag];
if (sender.state == UIGestureRecognizerStateBegan) {
}
else if (sender.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [sender translationInView:sender.view];
sender.view.center = CGPointMake(sender.view.center.x + translation.x, sender.view.center.y + translation.y);
[sender setTranslation:CGPointZero inView:sender.view];
}
else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled) {
for (UIView* blankView in self.blankViewContaninerList) {
if (CGRectIntersectsRect(sender.view.frame, blankView.frame) && blankView.tag != -999) {
__weak typeof(self) weakSelf = self;
UILabel* selectedLabel = (UILabel*)sender.view;
[self computeAnswerFromSelectedLabel:selectedLabel blankView:blankView onCompletion:^(BOOL isCorrectAnswer, NSString *selectedAnswer) {
if (isCorrectAnswer) {
[selectedLabel setUserInteractionEnabled:NO];
blankView.tag = -999; // Indicates that blank view already contains one label (blank space is already filled)
[UIView animateWithDuration:0.25 animations:^{
[sender.view setCenter:blankView.center];
} completion:^(BOOL finished) {
if (weakSelf.correctAnswerCount == weakSelf.totalOptionCount) {
// Your custom logic goes here, after all option dragged on their respective places.
}
}];
}
else{
[UIView animateWithDuration:0.25 animations:^{
[sender.view setFrame:CGRectMake(senderRect.origin.x, senderRect.origin.y, senderRect.size.width, senderRect.size.height)];
}];
}
isDragOnBlank = YES;
}];
}
}
if(!isDragOnBlank) {
[UIView animateWithDuration:0.25 animations:^{
[sender.view setFrame:CGRectMake(senderRect.origin.x, senderRect.origin.y, senderRect.size.width, senderRect.size.height)];
}];
}
}
}
此方法会告诉你拖动选项空白Y空间是正确的还是错误的
- (void)computeAnswerFromSelectedLabel:(UILabel*)selectedLabel
blankView:(UIView*)blankView
onCompletion:(void(^)(BOOL isCorrectAnswer, NSString* selectedAnswer))onCompletion {
NSInteger tagIndex = (blankView.tag - 600);
NSString* correctAnswer = self.card.questionDataModel.fillAnswers[tagIndex];
NSString* selectedAnswer = selectedLabel.text;
if ([correctAnswer isEqualToString:selectedAnswer]) {
self.correctAnswerCount++;
if (onCompletion) {
onCompletion(YES, selectedAnswer);
}
}
else {
self.wrongAnswerCount++;
// Shake the container view if dragging is wrong.
[self shakeView:self.fillBlankContainerView withOffest:8];
if(onCompletion){
onCompletion(NO, selectedAnswer);
}
}
}

请随意使用代码&改进高兴地欢迎:)
保持编码!
好的。现在是否有可能从uiwebview之外传递一个字符串以反映它们之间的空白?当我点击空格时,我会滑下一个包含单词(选项)的视图,点击这些单词将反映在所选的空白处。我可以这样做吗?我知道我将通过loadhtmlString为uiwebview加载html,这是否意味着我将更新htmlString并刷新uiwebview?如果我这样做,以前的投入会发生什么? – Diffy
您不必使用新的HTML字符串重新加载整个webview。你可以在那里使用Javascript方法。看到我更新了我的答案。 – sElanthiraiyan
谢谢兄弟!你一直在帮助很大。一切正常。现在我的问题是如何在点击文本框时不显示键盘?因为我想从uiwebview中点击文本字段时显示自定义视图。 – Diffy