UITextView 中的捏合结果不一致

发布于 2024-08-15 03:31:23 字数 2623 浏览 7 评论 0原文

我试图找出处理 UITextView 中捏合手势的最佳方法。目前,我一直在尝试在 UITextView 中处理所有问题,但得到的结果不一致。似乎它可以在触摸开始方法中捕获我的触摸,但它并不总是在触摸移动方法中捕获。

在视图中处理触摸并让 UITextView 传递多点触摸事件会更好吗?做一些棘手的事情(例如将 UITextView 放在滚动视图中)会更好吗?

此时,我想做的就是调整多点触控捏合或展开时的字体大小,我可以开始工作,但它并不一致,我认为我已经设法让 UITextView 比实际更加混乱得到结果。

我的控件是 UITextView 的子类并实现 UITextViewDelegate:

#import "MyUITextView.h"
@implementation MyUITextView

/* skipping unimportant code */


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches count] == 2)
    {
        NSLog(@"two touches");
        UITouch *first = [[touches allObjects] objectAtIndex:0];
        UITouch *second = [[touches allObjects] objectAtIndex:1];
        initialDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];

     }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touches moved");
    if([touches count] == 2)
    {
        self.scrollEnabled = NO;
        UITouch *first  = [[touches allObjects] objectAtIndex:0];
        UITouch *second = [[touches allObjects] objectAtIndex:1];
        CGFloat currentDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];
        if(initialDistance == 0)
            initialDistance = currentDistance;
        else if(currentDistance > initialDistance)
        {
            NSLog(@"zoom in");
            self.scrollEnabled = YES;
            self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] + 1.0f];
            self.text = self.text;
        }
        else if(currentDistance < initialDistance)
        {
            NSLog(@"zoom out");
            self.scrollEnabled = YES;
            self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] = 1.0f];
            self.text = self.text;
        }
    }    
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touches ended.");
    initialDistance = 0;
    [super touchesEnded:touches withEvent:event];

}

-(CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
{
    float x = toPoint.x - fromPoint.x;
    float y = toPoint.y - fromPoint.y;
    return sqrt(x*x + y*y);

}

-(BOOL)canBecomeFirstResponder
{   return NO; }

基本上,我尝试在屏幕上有两次触摸时禁用滚动,然后在完成后重新启用它。另外,禁用了成为第一响应者的能力,这样我就不必与复制和粘贴菜单作斗争。如果有更好的方法来做到这一点,通过在使用单点触摸时允许复制和粘贴菜单,我洗耳恭听。我想我基本上是在使用一个更高级的例子来第一次进入这个手势业务。

另外,由于控件正在处理自己的所有内容,因此我认为它不需要传递触摸事件,因为它自己正在处理它们。我错了吗?

最后,我的这个 UITextView 以编程方式创建并放置在 UINavigationControl 中。我不知道这是否有影响。

I'm trying to figure out the best way to handle pinch gestures in a UITextView. Currently I've been trying to handle it all in the UITextView, but I'm getting inconsistant results. It seems that it can catch my touches in the touches began method, but it doesn't always get caught in the touches moved method.

Would it be better to handle the touches in a View, and have the UITextView pass on the multitouch events? Would it be better to do something tricky like placing the UITextView in a scrollview?

At this point all I'd like to do is adjust the font size on a multitouch pinch or expand, which I can get to work, but it isn't consistant and I think I've managed to just confuse the UITextView more than actually get results.

My control is a subclass of UITextView and implements UITextViewDelegate:

#import "MyUITextView.h"
@implementation MyUITextView

/* skipping unimportant code */


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches count] == 2)
    {
        NSLog(@"two touches");
        UITouch *first = [[touches allObjects] objectAtIndex:0];
        UITouch *second = [[touches allObjects] objectAtIndex:1];
        initialDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];

     }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touches moved");
    if([touches count] == 2)
    {
        self.scrollEnabled = NO;
        UITouch *first  = [[touches allObjects] objectAtIndex:0];
        UITouch *second = [[touches allObjects] objectAtIndex:1];
        CGFloat currentDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];
        if(initialDistance == 0)
            initialDistance = currentDistance;
        else if(currentDistance > initialDistance)
        {
            NSLog(@"zoom in");
            self.scrollEnabled = YES;
            self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] + 1.0f];
            self.text = self.text;
        }
        else if(currentDistance < initialDistance)
        {
            NSLog(@"zoom out");
            self.scrollEnabled = YES;
            self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] = 1.0f];
            self.text = self.text;
        }
    }    
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touches ended.");
    initialDistance = 0;
    [super touchesEnded:touches withEvent:event];

}

-(CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
{
    float x = toPoint.x - fromPoint.x;
    float y = toPoint.y - fromPoint.y;
    return sqrt(x*x + y*y);

}

-(BOOL)canBecomeFirstResponder
{   return NO; }

Basically I've tried to disable the scrolling when I have two touches on the screen, and then re-enable it when I was done. Also, disabled the ability to become first responder so that I wouldn't have to be fighting with the copy and paste menu. If there is a better way to do this by allowing for the copy and paste menu when using a single touch I'm all ears. I think I'm basically working with a more advanced example for my first entry into this gesture business.

Also, since the control is handling all its own stuff, I didn't think it needed to pass on the touch events, since it is handling them itself. Am I wrong?

Finally, this UITextView of mine is created programatically and placed in a UINavigationControl. I don't know if that makes a difference or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(1

゛时过境迁 2024-08-22 03:31:23

我想我会从完整记录所有触摸和所有事件开始。确保记录触摸的视图属性。

您还可以子类化 UIWindow 以创建一个诊断类,该类将记录应用中的每次触摸。这对于准确了解触摸实际发生的位置和时间非常有用。您可能会发现触摸被路由到与您预期不同的视图。

正如 OP 的注释中所指出的,touchesMoved: 可以通过多点触摸手势移动的一次触摸来调用。因此,如果您启动两次触摸手势(例如捏合)但仅移动一根手指,则在 touchesMoved: 中您只会获得一次触摸。例如,人们经常通过放下拇指和食指然后仅移动食指来进行捏合。 (即使他们都移动,食指总是比拇指移动更长的距离,因为它更长。)

I think I would start by fully logging all touches and all events. Make sure to log the view property of the touches.

You can also subclass UIWindow to create a diagnostic class that will log every touch in the app. This can be very useful for seeing exactly where and when touches are actually occurring. You might find that the touches are being routed to different views than you expect.

As noted in the comments to the OP, touchesMoved: can be called by just one touch of a multitouch gesture moving. So if you start a two touch gesture like a pinch but only move one finger, you only get one touch in touchesMoved:. For example, people often perform a pinch by placing down their thumb and forefinger and then moving the forefinger only. (Even if they move both, the forefinger will always move over a longer distance than the thumb because it is longer.)

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