定义 UITextView 的最大方差

发布于 2024-12-07 08:41:47 字数 3338 浏览 1 评论 0原文

如果您有一个普通的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千纸鹤 2024-12-14 08:41:47

尝试添加 UISwipeGestureRecognizer 到视图并设置 cancelsTouchesInView 设置为 false,这样滑动手势就不会通过。这应该可以让您更准确地检测左右运动。

如果这不起作用,请实现您自己的 UIGestureRecognizer 子类并添加它。

编辑

您将手势识别器添加到控制器的 viewDidLoad 方法中的 UITextView 中。

在委托方法中,您不能在 gestureRecognizer:shouldReceiveTouch: 中返回 NO,因为这意味着手势识别器不会检查传入的触摸对象。在您的情况下,当水平滑动时您希望返回 YES ,否则返回 NO ,因此垂直滑动会被传递,而水平滑动则由您完成处理。

Try adding an UISwipeGestureRecognizer to the view and set cancelsTouchesInView 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's viewDidLoad method.

In your delegate methods, you can't return NO in gestureRecognizer:shouldReceiveTouch: because it means the gesture recognizer won't examine the incoming touch object. In your case you want to return YES when the swipe is horizontal and NO otherwise, so vertical swipes are passed through while horizontal swipe is completed handled by you.

烟酉 2024-12-14 08:41:47

不需要子类。将 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文