5

想象一下你的键盘。想象一下自己将一根手指放在一个键上,然后(在按住的同时)将手指一直移动到键盘上的另一个键上。现在,假设键盘上的每个键都是UIButton. 当您将手指放在当前键上时,该键 ( UIButton) 会突出显示。然后,当用户移动到另一个键时,第一个键不再突出显示,而当前按下的键被突出显示。

现在,我有一个 6 x 8 的 UIButton 网格,每个 53 x 53 像素。所以,我有 48 UIButtons。我想复制这种想法。用户手指按下的按钮会有一个稍微亮一点的图像(看起来像被选中的那样),而所有其他按钮都不会稍微亮一点。

这是我对如何解决这个问题的想法,

1) 创建所有 48UIButtonsviewDidLoad. 将较亮的图像添加到UIControlStateHighlighted所有UIButtons.

2)添加某种方式targettouchUpOutside某种方式使当前按钮不突出显示且不可用。(也许设置突出显示和userInteractionEnabled否)。但是,我怎样才能知道要使用的下一个按钮呢?我怎么能说我希望UIButton用户手指所在的特定位置突出显示并用于检测手势和东西。

此外,此touchUpOutside方法可能不起作用,因为所有按钮都彼此相邻,我认为您必须将其拖得很远才能运行 this touchUpOutside

同样重要的是要注意按钮的行和列不相等。有时一个按钮实际上是一个UIImage但看起来像一个UIButton。因此,出于某种原因进行某种快速枚举比较帧是行不通的。

4

2 回答 2

4

两个观察:

  1. 我通常使用手势识别器来处理这样的事情,而不是各种touchUp...方法。

  2. 我知道你说过你不想通过子视图快速枚举,但为什么不呢?仅仅因为某些类与其他类不同不是问题(因为您可以只测试该isKindOfClass方法)。(而且,顺便说一句,我不知道为什么有些会是按钮,有些不会。)仅仅因为它们没有排列真的没有区别,要么。

无论如何,对于这样的事情,我经常将手势识别器放在共享父视图(例如通常是视图控制器的视图)上,然后枚举子视图以查看当前 CGPoint 包含在哪个视图中?

CGPoint location = [sender locationInView:self.view];

for (UIView *subview in self.view.subviews)
{
    if (CGRectContainsPoint(subview.frame, location))
    {
        // do your appropriate highlighting

        if ([subview isKindOfClass:[UIButton class]])
        {
            // something for buttons
        }
        else if ([subview isKindOfClass:[UIImageView class]])
        {
            // something for imageviews
        }

        return;
    }
}

我不知道这对你是否有意义,但对我来说似乎最简单。如果你澄清你的意图,也许我可以进一步完善我的答案。

作为一个实际的例子,你可以定义一个连续的手势识别器来跟踪被点击的第一个和最后一个子视图(如果你没有在子视图上开始你的手势,则不会生成手势,如果你不' t 在子视图上停止手势,它会取消整个操作),例如:

@interface SubviewGestureRecognizer : UIGestureRecognizer

@property (nonatomic,strong) UIView *firstSubview;
@property (nonatomic,strong) UIView *currentSubview;

@end

@implementation SubviewGestureRecognizer

- (id) initWithTarget:(id)target action:(SEL)action
{
    self = [super initWithTarget:target action:action];
    if (self)
    {
        self.firstSubview = nil;
        self.currentSubview = nil;
    }

    return self;
}

// you might want to tweak this `identifySubview` to only look 
// for buttons and imageviews, or items with nonzero tag properties, 
// or recursively navigate if it encounters container UIViews 
// or whatever suits your app

- (UIView *)identifySubview:(NSSet *)touches
{
    CGPoint location = [[touches anyObject] locationInView:self.view];

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

    return nil;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];

    if ([touches count] != 1)
    {
        self.state = UIGestureRecognizerStateFailed;
        return;
    }

    self.firstSubview = [self identifySubview:touches];
    self.currentSubview = self.firstSubview;

    if (self.firstSubview == nil)
        self.state = UIGestureRecognizerStateFailed;
    else
        self.state = UIGestureRecognizerStateBegan;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    if (self.state == UIGestureRecognizerStateFailed) return;

    self.currentSubview = [self identifySubview:touches];

    self.state = UIGestureRecognizerStateChanged;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    self.currentSubview = [self identifySubview:touches];

    if (self.currentSubview != nil)
        self.state = UIGestureRecognizerStateEnded;
    else
        self.state = UIGestureRecognizerStateFailed;
}

- (void)reset
{
    [super reset];

    self.firstSubview = nil;
    self.currentSubview = nil;
}

然后,您可以在以下位置进行设置viewDidLoad

SubviewGestureRecognizer *recognizer = [[SubviewGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouches:)];
[self.view addGestureRecognizer:recognizer];

然后像这样定义你的处理程序(这适用于按钮和图像视图,利用两者都支持的事实setHighlighted):

- (void)handleTouches:(SubviewGestureRecognizer *)sender
{
    static UIControl *previousControl = nil;

    if (sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged)
    {
        if (sender.state == UIGestureRecognizerStateBegan)
            previousControl = nil;

        UIView *subview = sender.currentSubview;
        if (previousControl != subview)
        {
            // reset the old one (if any)

            [previousControl setHighlighted:NO];

            // highlight the new one

            previousControl = (UIControl *)subview;
            [previousControl setHighlighted:YES];
        }
    }
    else if (sender.state == UIGestureRecognizerStateEnded)
    {
        if (previousControl)
        {
            [previousControl setHighlighted:NO];
            NSLog(@"successfully touchdown on %@ and touchup on %@", sender.firstSubview, sender.currentSubview);
        }
    }
    else if (sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed)
    {
        [previousControl setHighlighted:NO];
        NSLog(@"cancelled/failed gesture");
    }
}
于 2012-08-12T03:25:27.287 回答
0

这是一个相当简单的方法来做到这一点。假设您正在以编程方式创建按钮(使用界面生成器执行此操作将是一个巨大的痛苦)。此方法适用于 UIViewController、UIView 和 UIGestureRecognizer 的子类。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    //get the touch object
    UITouch *myTouch = [touches anyObject];

    //get the location of the touch
    CGPoint *myPoint = [myTouch locationInView:self.view];

    //detect if the touch is in one of your buttons
    if ( CGRectContainsPoint(myButton.frame, myPoint){
        /*do whatever needs to be done when the button is pressed
        repeat the CGRectContainsPoint for all buttons,
        perhaps using a while or for loop to look through an array?*/
    }

}

此方法仅检测用户何时放下手指,您将需要使用这些方法来检测其他动作:

touchesMoved:withEvent检测手指何时在屏幕上移动而不抬起

touchesEnded:withEvent检测手指何时离开屏幕

touchesCancelled:withEvent:检测何时中断应用程序,例如接听电话或锁定屏幕

于 2012-08-12T06:20:44.233 回答