如何在仍然按住手指的同时从使用一个UIButton切换到另一个UIButton?

时间:2012-08-12 01:38:06

标签: iphone ios uibutton

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

现在,我有一个6 x 8网格的UIButtons,每个53 x 53像素。所以,我有48 UIButtons。我想复制这种想法。用户手指所在的按钮将具有稍微更轻的图像(看起来像选择的那样),并且所有其他图像将不会稍微更轻。

以下是关于如何解决这个问题的想法,

1)在UIButtons中创建所有48 viewDidLoad。为所有UIControlStateHighlighted添加较轻的图片到UIButtons

2)为target添加某种touchUpOutside,以某种方式使当前按钮不突出显示且不可用。 (可以设置突出显示的userInteractionEnabled为否)。但是,我怎么能告诉下一个按钮被使用?我怎么能说我希望用户手指所在的特定UIButton突出显示并用于检测手势和内容。

此外,这个touchUpOutside方法可能无效,因为所有按钮都是彼此相邻的,我认为你必须拖远才能运行此touchUpOutside

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

2 个答案:

答案 0 :(得分:4)

两个观察结果:

  1. 我通常会将手势识别器用于此类内容,而不是各种touchUp...方法。

  2. 我知道你说你不希望通过子视图快速枚举,但为什么不呢?仅仅因为有些类不同于其他类不是问题(因为你可以只测试isKindOfClass方法)。 (而且,顺便说一句,我不确定为什么有些会是按钮,有些则不会。)只是因为它们没有排列确实没有任何区别。

  3. 无论如何,对于这样的东西,我经常将手势识别器放在共享父视图上(例如通常是视图控制器的视图),然后通过子视图枚举以查看当前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;
        }
    }
    

    我不知道这对你有什么意义,但对我来说似乎最容易。如果你澄清了你的意图,也许我可以进一步完善我的答案。

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

    @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");
        }
    }
    

答案 1 :(得分: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:检测到某些内容中断了应用,例如接听电话或锁定屏幕