【问题标题】:Draggable UIButton does not respond to UIControlEvents可拖动的 UIButton 不响应 UIControlEvents
【发布时间】:2011-09-19 15:25:53
【问题描述】:

当创建 Draggable UIButton 时,拖动事件按应有的方式工作,但是,我无法弄清楚为什么 UIControlEvents 在按钮被按下而不响应时没有响应被拖了。

创建按钮

DraggableButton * camera = [DraggableButton buttonWithType:UIButtonTypeCustom];
[camera setFrame:CGRectMake(160,5,149,40)];
[camera setImage: [UIImage imageWithContentsOfFile:cameraMode] forState:UIControlStateNormal];
[camera setTitle: @"Camera" forState:UIControlStateNormal];  // never gets called.
[camera addTarget:self action:@selector(openCamera) forControlEvents:UIControlEventTouchUpInside];
[buttonView addSubview: camera];

可拖动按钮

@interface DraggableButon : UIButton
{
@private float deltaX;
@private float deltaY;
    CGPoint startLocation;
    BOOL    dragging;
}
@end
@implementation DraggableButon
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesMoved:touches withEvent:event];

    if ( ! draggable ) return;

    dragging = YES;
    camera.enabled = NO;
    flash.enabled = NO;

    // Calculate offset
    CGPoint pt = [[[event allTouches] anyObject] locationInView:buttonView];
    deltaX = pt.x - startLocation.x;
    deltaY = pt.y - startLocation.y;

    float xx;
    if ( IPAD ) { xx = buttonView.center.x + deltaX; } else { xx = 160; }
    CGPoint newcenter = CGPointMake(xx, buttonView.center.y + deltaY);

    // Set new location
    buttonView.center = newcenter;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesBegan:touches withEvent:event];

    if ( ! draggable ) return;

    // Calculate and store offset, and pop view into front if needed
    CGPoint pt = [[[event allTouches] anyObject] locationInView:buttonView];
    startLocation = pt;
    [[self superview] bringSubviewToFront:buttonView];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{        
    [super touchesEnded:touches withEvent:event];

    dragging = YES;
    if ( dragging )
    {
        camera.enabled = YES;
        flash.enabled = YES;

        //NSLog(@"touchesEnded: buttonView.frame.origin.x: %3.2f, buttonView.frame.origin.y: %3.2f",buttonView.frame.origin.x,buttonView.frame.origin.y);
        rectFromString = [NSString stringWithFormat:@"{{%3.2f,%3.2f},{320,50}}",buttonView.frame.origin.x,buttonView.frame.origin.y]; 
        NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithContentsOfFile: SETTINGS_FILE];
        [dict setObject:rectFromString forKey:@"kCGRectFromString"];
        [dict writeToFile: SETTINGS_FILE atomically:YES];
    }else{
        [self sendActionsForControlEvents:UIControlEventTouchUpInside];
    }
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
{    
    [super touchesCancelled:touches withEvent:event];
}
@end

【问题讨论】:

    标签: ios uibutton touchesmoved uicontrolevents


    【解决方案1】:

    未调用该操作,因为您覆盖了触摸事件并且您没有将它们进一步发送到super。您可以添加一个新变量(我们称之为dragged)。在touchesBegan: 将其设置为NO,在touchesMoved:touchesEnded: 设置为YES,如果设置为NO,则调用[self sendActionsForControlEvents:UIControlEventTouchUpInside];

    @interface DraggableButon : UIButton
    {
    @private float deltaX;
    @private float deltaY;
        CGPoint startLocation;
        BOOL    dragging;
    }
    @end
    @implementation DraggableButon
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    {
        dragging=NO;
    
        if ( ! draggable ) return;
    
        // Calculate and store offset, and pop view into front if needed
        CGPoint pt = [[[event allTouches] anyObject] locationInView:buttonView];
        startLocation = pt;
        [[self superview] bringSubviewToFront:buttonView];
    }
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
    {
        dragging=YES;
    
        if ( ! draggable ) return;
    
        camera.enabled = NO;
        flash.enabled = NO;
    
        // Calculate offset
        CGPoint pt = [[[event allTouches] anyObject] locationInView:buttonView];
        deltaX = pt.x - startLocation.x;
        deltaY = pt.y - startLocation.y;
    
        float xx;
        if ( IPAD ) { xx = buttonView.center.x + deltaX; } else { xx = 160; }
        CGPoint newcenter = CGPointMake(xx, buttonView.center.y + deltaY);
    
        // Set new location
        buttonView.center = newcenter;
    }
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
    {        
        if(!dragging){  // or if(!dragging||!draggable)
            [self sendActionsForControlEvents:UIControlEventTouchUpInside];
            return;
        }
    
        camera.enabled = YES;
        flash.enabled = YES;
    
        //NSLog(@"touchesEnded: buttonView.frame.origin.x: %3.2f, buttonView.frame.origin.y: %3.2f",buttonView.frame.origin.x,buttonView.frame.origin.y);
        rectFromString = [NSString stringWithFormat:@"{{%3.2f,%3.2f},{320,50}}",buttonView.frame.origin.x,buttonView.frame.origin.y]; 
        NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithContentsOfFile: SETTINGS_FILE];
        [dict setObject:rectFromString forKey:@"kCGRectFromString"];
        [dict writeToFile: SETTINGS_FILE atomically:YES];
    }
    @end
    

    【讨论】:

    • 相同的结果。当拖动然后放开时,动作触发。
    • 你能发布你更新的实现吗?如果按钮被拖动,则dragged 的值应为touchesEnded 中的YES,并且不应发送sendActionsForControlEvents(因此不应触发该操作)
    • 我已经更新了答案 - 删除了 super 呼叫(因为我们正在呼叫 sendActionsForControlEvents)并设置 dragging
    • 完美,成功了。知道为什么点击不会改变按钮的状态吗?当点击它时它应该正常工作(谢谢),但它不会突出显示按钮。这没什么大不了的,但想知道是否也可以补救。
    • 我相信你必须在touchesBeganself.highlighted 设置为YES,在touchesEndedtouchesCanceled 设置为NO。我还没有测试过这个,所以我不确定它的效果如何。
    【解决方案2】:

    您是否调试过,是否调用了触摸事件函数? 并且简单的按下动作应该在touchesEnded: withEvent:中实现

    既然是继承自UIButton,有没有试过像addTarget: action: forControlEvents:一样直接添加action事件?

    【讨论】:

    • 问题是,我需要按钮在拖动时拖动,而当简单按下时,我需要它执行其连接的方法。因此,如果我将该方法放在touchesEnded 中,则每次拖动按钮时都会触发。
    • 是的,原始问题中列出了addTarget:action:forControlEvents:
    猜你喜欢
    • 2013-09-26
    • 2017-06-12
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多