定义 UITextView 的最大方差
如果您有一个普通的 UITextView,其中包含大量文本,您可以上下滑动:
- 如果您在非常水平的线上向左或向右滑动
- ,那么如果您以非常水平的方向向左或向右滑动 ,则不会发生任何事情。轻微的角度,你会向上或向下滑动
因此显然有某种类定义告诉 UITextView
何时对滑动做出反应,何时不做出反应。我猜想类似于最大方差常数。
我的问题是我试图对 UITextView 进行子类化以启用左/右滑动。但是,您需要沿直线滑动,否则,您将得到向上或向下滑动。所以我的问题是是否有办法重新定义 UITextView 的标准方差变量?
这是我的子类 .m 文件。请注意,kMaximumVariance
实际上没有任何效果,因为它会被标准 UITextView
类提供的任何方差覆盖:
//
// SwipeTextView.m
// Swipes
//
#import "SwipeTextView.h"
#import "PageView.h"
#define kMinimumGestureLength 15
#define kMaximumVariance 100
@implementation SwipeTextView
@synthesize delegate, gestureStartPoint;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch =[touches anyObject];
gestureStartPoint = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self resignFirstResponder]; // this hides keyboard if horizonal swipe
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self];
CGFloat deltaXX = (gestureStartPoint.x - currentPosition.x); // positive = left, negative = right
CGFloat deltaYY = (gestureStartPoint.y - currentPosition.y); // positive = up, negative = down
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); // will always be positive
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); // will always be positive
NSLog(@"deltaXX (%.1f) deltaYY (%.1f) deltaX (%.1f) deltaY (%.1f)",deltaXX, deltaYY, deltaX, deltaY);
if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) {
if (deltaXX > 0) {
NSLog(@"Horizontal Left swipe - FINISHED detected");
}
else {
NSLog(@"Horizontal Right swipe - FINISHED detected");
}
}
}
@end
编辑:
建议取消触摸到达 UITextView
(见下文):
// Prevent recognizing touches
- (BOOL)gestureRecognizer:(UISwipeGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionLeft) {
// Left swipe: I want to handle this
return YES;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionRight) {
// Right swipe: I want to handle this
return YES;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionUp) {
// Up swipe: textView needs to handle this
return NO;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionDown) {
// Down swipe: textView needs to handle this
return NO;
} else
return YES;
}
-(void)viewDidLoad
{
UITapGestureRecognizer *GesRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething:)];
[GesRec setCancelsTouchesInView:NO];
[self addGestureRecognizer:GesRec];
[GesRec release];
}
-(void)doSomething
{
NSLog(@"doSomething");
}
If you have a normal UITextView
with loads of text in it you can swipe up and down:
- if you swipe left or right in a very horizontal line, nothing will happen
- if you swipe left or right with a very slight angle, you will swipe up or down
So there is obviously some kind of class definition which tells the UITextView
when to react to a swipe and when not to. Something like a maximumVariance constant, I guess.
My problem is that I'm trying to subclass an UITextView
to enable left/right swipe. However, you will need to swipe in a pretty straight line, otherwise, you'll get an up or down swipe. So my question is if there is someway to re-define the standard variance variable of an UITextView?
Here is my subclass .m file. Note that the kMaximumVariance
doesn't really have any effect as this is overwritten by whatever variance the standard UITextView
class provides:
//
// SwipeTextView.m
// Swipes
//
#import "SwipeTextView.h"
#import "PageView.h"
#define kMinimumGestureLength 15
#define kMaximumVariance 100
@implementation SwipeTextView
@synthesize delegate, gestureStartPoint;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch =[touches anyObject];
gestureStartPoint = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self resignFirstResponder]; // this hides keyboard if horizonal swipe
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self];
CGFloat deltaXX = (gestureStartPoint.x - currentPosition.x); // positive = left, negative = right
CGFloat deltaYY = (gestureStartPoint.y - currentPosition.y); // positive = up, negative = down
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); // will always be positive
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); // will always be positive
NSLog(@"deltaXX (%.1f) deltaYY (%.1f) deltaX (%.1f) deltaY (%.1f)",deltaXX, deltaYY, deltaX, deltaY);
if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) {
if (deltaXX > 0) {
NSLog(@"Horizontal Left swipe - FINISHED detected");
}
else {
NSLog(@"Horizontal Right swipe - FINISHED detected");
}
}
}
@end
EDIT:
Suggestion to cancel touches reaching UITextView
(see below):
// Prevent recognizing touches
- (BOOL)gestureRecognizer:(UISwipeGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionLeft) {
// Left swipe: I want to handle this
return YES;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionRight) {
// Right swipe: I want to handle this
return YES;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionUp) {
// Up swipe: textView needs to handle this
return NO;
}
if ([gestureRecognizer direction] == UISwipeGestureRecognizerDirectionDown) {
// Down swipe: textView needs to handle this
return NO;
} else
return YES;
}
-(void)viewDidLoad
{
UITapGestureRecognizer *GesRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething:)];
[GesRec setCancelsTouchesInView:NO];
[self addGestureRecognizer:GesRec];
[GesRec release];
}
-(void)doSomething
{
NSLog(@"doSomething");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试添加
UISwipeGestureRecognizer
到视图并设置cancelsTouchesInView
设置为 false,这样滑动手势就不会通过。这应该可以让您更准确地检测左右运动。如果这不起作用,请实现您自己的
UIGestureRecognizer
子类并添加它。编辑
您将手势识别器添加到控制器的
viewDidLoad
方法中的UITextView
中。在委托方法中,您不能在
gestureRecognizer:shouldReceiveTouch:
中返回NO
,因为这意味着手势识别器不会检查传入的触摸对象。在您的情况下,当水平滑动时您希望返回YES
,否则返回NO
,因此垂直滑动会被传递,而水平滑动则由您完成处理。Try adding an
UISwipeGestureRecognizer
to the view and setcancelsTouchesInView
to false so the swipe gesture is not passed through. This should let you detect left and right motion more accurately.If this doesn't do the trick, implement your own subclass of
UIGestureRecognizer
and add that instead.Edit
You add the gesture recognizer to the
UITextView
in your controller'sviewDidLoad
method.In your delegate methods, you can't return
NO
ingestureRecognizer:shouldReceiveTouch:
because it means the gesture recognizer won't examine the incoming touch object. In your case you want to returnYES
when the swipe is horizontal andNO
otherwise, so vertical swipes are passed through while horizontal swipe is completed handled by you.不需要子类。将 textView.userInteractionEnabled 设置为 NO,然后在 textView 上放置一个透明的 UIView。在 UIView 上以您想要的方式处理触摸和手势,并使 textView 以编程方式响应这些操作。
No subclass needed. set textView.userInteractionEnabled to NO and than put a transparent UIView over your textView. handle touches and gestures anyway you want on that UIView and make the textView respond to these programatically.