繁体   English   中英

如何检测拖动到那里的子视图中的触摸(或最快的方法来获取哪个子视图在其父视图的轻击下面)

[英]How to detect a touch in a subview that was dragged there (or fastest way to get which subview is underneath a tap in its superview)

我有一个超级视图,并且有很多子视图。 我希望用户能够在超级视图内拖动其手指,并且当他们在子视图上拖动时,该子视图会发生变化。

我需要这样做非常有效,因为更改可以很快发生。

到目前为止,我尝试过的是,在超级视图中,我可以从touchesBegan:withEvent:和touchesMoved:withEvent中获取触摸事件:这两个结合在一起为我提供了我需要的所有触摸。 每次调用这些方法时,我都必须遍历所有子视图并像这样进行测试

for (UIView *view in self.subviews) {
    if (CGRectContainsPoint(view.frame, touchPoint) {
        return view;
    }
}

然后根据需要更改该视图。 问题是,根据我的基准测试,此过程只有两个过程。

我立即想到的是让子视图本身检测到触摸,然后在点击时发布通知或类似内容。 这样,我不必在每个异常的触摸事件中都遍历超级视图中的所有对象。

我遇到的问题是,我还没有找到一种方法来获取子视图本身,以检测它们是否在被拖动并且触摸实际上源自其他UIView时被触摸了。

我愿意接受任何建议来加快第一个过程,或者采用其他方法来完成此过程。

由于子视图位于网格上,并且如果它们的大小相等,那么您应该能够直接计算突出显示的子视图。 您只需要在创建时将它们的引用存储在2D数组中,为获得性能,我建议使用c数组。

int x = touchPoint.x/viewWidth;
int y = touchPoint.y/viewHeight;
return views[x][y];

根据您的版式,应考虑视图之间的某些边框边距或间距。

这样,您不需要迭代子视图数组,也不需要执行所有这些CGRectContainsPoint计算。

应该很容易:

MyViewController.h

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController

@end

MyViewController.m

#import "MyViewController.h"

#define SIDE_LENGTH 60
#define NUM_SQUARES 15

@implementation MyViewController
{
    UIView *_selectedView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self populateView];
}

- (void)populateView
{
    for (int i = 0; i < 15; ++i)
    {
        CGRect frame = CGRectMake(drand48() * self.view.frame.size.width - SIDE_LENGTH,
                                   drand48() *self.view.frame.size.height - SIDE_LENGTH,
                                   SIDE_LENGTH,
                                   SIDE_LENGTH);
        UIView *view = [[UIView alloc] initWithFrame:frame];
        view.backgroundColor = [UIColor colorWithRed:drand48()
                                               green:drand48()
                                                blue:drand48()
                                               alpha:1.0f];
        view.layer.cornerRadius = SIDE_LENGTH / 2.0f;    // cuz circles r pretty
        [self.view addSubview:view];
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    for (UIView *view in self.view.subviews)
    {
        if (CGRectContainsPoint(view.frame, location)) {
            _selectedView = view;
            break;
        }
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    _selectedView.center = location;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    _selectedView.center = location;
}

@end

当然,对您而言,只需摆脱populateView方法即可。 我只是用它来演示它作为嵌入式课程的工作方式。

如果您正在寻找速度,请子类化UIView并执行以下操作:MyView.h

#import <UIKit/UIKit.h>
@class MyView;

@interface MyView : UIView

@end

MyView.m

@implementation MyView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.superview];
    self.center = location;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.superview];
    self.center = location;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.superview];
    self.center = location;
}


@end

然后MyViewController.m变得更加简单和快捷:

#import "MyViewController.h"
#import "MyView.h"
#define SIDE_LENGTH 60
#define NUM_SQUARES 15

@implementation MyViewController
{
    UIView *_selectedView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self populateView];
}

- (void)populateView
{
    for (int i = 0; i < 15; ++i)
    {
        CGRect frame = CGRectMake(drand48() * self.view.frame.size.width - SIDE_LENGTH,
                                   drand48() *self.view.frame.size.height - SIDE_LENGTH,
                                   SIDE_LENGTH,
                                   SIDE_LENGTH);
        MyView *view = [[MyView alloc] initWithFrame:frame];
        view.backgroundColor = [UIColor colorWithRed:drand48()
                                               green:drand48()
                                                blue:drand48()
                                               alpha:1.0f];
        view.layer.cornerRadius = SIDE_LENGTH / 2.0f;
        [self.view addSubview:view];
    }
}

@end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM