IOS/Objective-C:使用 UITapRecognizer 从大小发生变化的视图中检测点击
IOS/Objective-C: Detect Taps Using UITapRecognizer from View that Changes in Size
已编辑
我有一个带有 UITapGestureRecognizer 的文本视图来识别人们点击的单词。然而,UITextVIew 本身的大小会根据加载到 textView 中的文本数量而改变。现在,textView 无法识别 textview 中超出屏幕初始大小的文本的任何点击。
点击识别器当前已在 viewDidLoad 中初始化,因为我只想创建一次。因此,它是在布局视图之前创建的。我应该将它移动到 viewwillappear 还是在已知 textview 的大小后触发的其他一些方法?或者有没有办法让 tapRecognizer 知道 textview 现在更大了?
屏幕使用自动播放,所以这可能是部分问题。
//This is how the recognizer is created in viewdidload:
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
action:@selector(handleTap:)];
tapList.cancelsTouchesInView = NO;
[self.myView addGestureRecognizer:tapRec];
//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
UITextView *textView = (UITextView *)recognizer.view;
CGPoint location = [recognizer locationInView:textView];
CGPoint position = CGPointMake(location.x, location.y);
UITextPosition *tapPosition = [textView closestPositionToPoint:position];
UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
NSString *tappedLine = [textView textInRange:textRange];
}
//This is where size of view is changed in response to quantity of text in viewwillappear
CGFloat fixedWidth = myView.frame.size.width;
//MAXFLOAT IS THE maximum float system allows
CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = myView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
myView.frame = newFrame;
[self.myView sizeToFit];
self.myView.editable = NO;
self.myView.scrollEnabled=NO;
感谢您的任何建议。
我用你的代码做了小测试。
对我来说一切正常。我添加了每 7 秒更改一次文本的计时器以进行测试。
更改大小后,我始终可以点击具有新大小的 textView 中的任何文本。
一些额外的代码可能有问题?
我的测试项目xCode9.2:https://ufile.io/ngo47
#import "ViewController.h"
@interface ViewController ()
{
IBOutlet UITextView* myView;
NSTimer* timer;
}
@end
@implementation ViewController
//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
UITextView *textView = (UITextView *)recognizer.view;
CGPoint location = [recognizer locationInView:textView];
CGPoint position = CGPointMake(location.x, location.y);
UITextPosition *tapPosition = [textView closestPositionToPoint:position];
UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
NSString *tappedLine = [textView textInRange:textRange];
NSLog(@"%@", tappedLine);
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self resizeView];
}
- (void)resizeView{
//This is where size of view is changed in response to quantity of text in viewwillappear
CGFloat fixedWidth = myView.frame.size.width;
//MAXFLOAT IS THE maximum float system allows
CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = myView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
myView.frame = newFrame;
[self->myView sizeToFit];
self->myView.editable = NO;
self->myView.scrollEnabled=NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
//This is how the recognizer is created in viewdidload:
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
action:@selector(handleTap:)];
//tapList.cancelsTouchesInView = NO;
[self->myView addGestureRecognizer:tapRec];
NSArray* someTexts = @[@"text1, text1, text1, text1, text1, text1, text1, text1, text1, text1",
@"text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2",
@"text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, ",
];
static NSInteger textIndex = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:7.0 repeats:YES block:^(NSTimer * timer){
self->myView.text = someTexts[textIndex];
[self resizeView];
textIndex ++;
if (textIndex >= someTexts.count) {
textIndex = 0;
}
}];
}
@end
已编辑
我有一个带有 UITapGestureRecognizer 的文本视图来识别人们点击的单词。然而,UITextVIew 本身的大小会根据加载到 textView 中的文本数量而改变。现在,textView 无法识别 textview 中超出屏幕初始大小的文本的任何点击。
点击识别器当前已在 viewDidLoad 中初始化,因为我只想创建一次。因此,它是在布局视图之前创建的。我应该将它移动到 viewwillappear 还是在已知 textview 的大小后触发的其他一些方法?或者有没有办法让 tapRecognizer 知道 textview 现在更大了?
屏幕使用自动播放,所以这可能是部分问题。
//This is how the recognizer is created in viewdidload:
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
action:@selector(handleTap:)];
tapList.cancelsTouchesInView = NO;
[self.myView addGestureRecognizer:tapRec];
//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
UITextView *textView = (UITextView *)recognizer.view;
CGPoint location = [recognizer locationInView:textView];
CGPoint position = CGPointMake(location.x, location.y);
UITextPosition *tapPosition = [textView closestPositionToPoint:position];
UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
NSString *tappedLine = [textView textInRange:textRange];
}
//This is where size of view is changed in response to quantity of text in viewwillappear
CGFloat fixedWidth = myView.frame.size.width;
//MAXFLOAT IS THE maximum float system allows
CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = myView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
myView.frame = newFrame;
[self.myView sizeToFit];
self.myView.editable = NO;
self.myView.scrollEnabled=NO;
感谢您的任何建议。
我用你的代码做了小测试。 对我来说一切正常。我添加了每 7 秒更改一次文本的计时器以进行测试。 更改大小后,我始终可以点击具有新大小的 textView 中的任何文本。 一些额外的代码可能有问题?
我的测试项目xCode9.2:https://ufile.io/ngo47
#import "ViewController.h"
@interface ViewController ()
{
IBOutlet UITextView* myView;
NSTimer* timer;
}
@end
@implementation ViewController
//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
UITextView *textView = (UITextView *)recognizer.view;
CGPoint location = [recognizer locationInView:textView];
CGPoint position = CGPointMake(location.x, location.y);
UITextPosition *tapPosition = [textView closestPositionToPoint:position];
UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
NSString *tappedLine = [textView textInRange:textRange];
NSLog(@"%@", tappedLine);
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self resizeView];
}
- (void)resizeView{
//This is where size of view is changed in response to quantity of text in viewwillappear
CGFloat fixedWidth = myView.frame.size.width;
//MAXFLOAT IS THE maximum float system allows
CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = myView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
myView.frame = newFrame;
[self->myView sizeToFit];
self->myView.editable = NO;
self->myView.scrollEnabled=NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
//This is how the recognizer is created in viewdidload:
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
action:@selector(handleTap:)];
//tapList.cancelsTouchesInView = NO;
[self->myView addGestureRecognizer:tapRec];
NSArray* someTexts = @[@"text1, text1, text1, text1, text1, text1, text1, text1, text1, text1",
@"text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2",
@"text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, ",
];
static NSInteger textIndex = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:7.0 repeats:YES block:^(NSTimer * timer){
self->myView.text = someTexts[textIndex];
[self resizeView];
textIndex ++;
if (textIndex >= someTexts.count) {
textIndex = 0;
}
}];
}
@end