2013-03-23 10 views
9

Trascino 2 IBActions da un UIButton, uno con evento touchDown e il secondo con trascinamento Interno.Come implementare due IBActions in UIButton senza sovrapposizione?

- (IBAction)clickButton:(UIButton *)sender { 
    NSLog(@"Click Button"); 
} 

- (IBAction)dragInsideButton:(UIButton *)sender { 
    NSLog(@"Drag Button"); 
} 

Ma quando si trascina all'interno, anche l'azione touchDown viene attivata.

Come disattivare l'evento touchDown durante il trascinamento.

Grazie!

+0

Solo una supposizione, fare un BOOL e il check-in sia il metodo e capovolgere l'azione: '- (void) removeTarget: action: ' –

+0

Vuoi anche il contrario, ovvero se touchDown è attivato devi trascinare il cursore per non accadere se l'utente inizia a trascinare? L'unico modo per farlo funzionare sarà con un leggero ritardo all'inizio per vedere se inizia un trascinamento. Se questo non è accettabile, allora devi andare con un design diverso. – rdelmar

risposta

4

ho risolto un problema come questo con l'utilizzo di trascinare gli eventi

aggiungere eventi al pulsante nel file di .xib o programatically.

è a livello di codice:

[mybut addTarget:self action:@selector(dragBegan:withEvent:) 
    forControlEvents: UIControlEventTouchDown]; 
    [mybut addTarget:self action:@selector(dragMoving:withEvent:) 
    forControlEvents: UIControlEventTouchDragInside]; 
    [mybut addTarget:self action:@selector(dragEnded:withEvent:) 
    forControlEvents: UIControlEventTouchUpInside | 
    UIControlEventTouchUpOutside]; 

poi defininitons di eventi sono:

- (void) dragBegan: (UIButton *) c withEvent:ev 
{ 
    NSLog(@"dragBegan......"); 
    count=NO;//bool Value to decide the Down Event 
    c.tag=0; 
    [self performSelector:@selector(DownSelected:) withObject:mybut afterDelay:0.1]; 
//user must begin dragging in 0.1 second else touchDownEvent happens 

} 

- (void) dragMoving: (UIButton *) c withEvent:ev 
{ 
    NSLog(@"dragMoving.............."); 
    c.tag++; 
} 

- (void) dragEnded: (UIButton *) c withEvent:ev 
{ 
    NSLog(@"dragEnded.............."); 
    if (c.tag>0 && !count) 
    { 

     NSLog(@"make drag events"); 

    } 

} 



-(void)DownSelected:(UIButton *)c 
{ 
    if (c.tag==0) { 
     NSLog(@"DownEvent"); 
     count=YES;//count made Yes To interrupt drag event 
    } 

} 
+0

Modo intelligente! Ma touchDown target diventa un evento touchUpInside. – Alex

+0

ho modificato la mia risposta. – meth

0

Io non sono sicuro che funzionerà, ma si può provare

- (IBAction)dragInsideButton:(UIButton *)sender { 
    [sender removeTarget:self forSelector:@selector(clickButton:) forControlEvent:UIControlEventTouchDown]; 
} 
+0

Grazie! Non funziona perché touchDown fa fuoco prima di trascinare. – Alex

0

ho ricevuto da Two action methods for an UIButton; next track and seek forward:

cambiare come il vostro requisito.

Personalmente mi limito a tenere traccia dello stato del pulsante con un numero intero sul controller di visualizzazione o all'interno di una sottoclasse di pulsanti. Se si tiene traccia di ciò che sta facendo il pulsante, è possibile controllare cosa fanno ciascuna azione. Nel file .h mettere in qualche cose come questa:

enum { 
    MyButtonScanning, 
    MyButtonStalling, 
    MyButtonIdle 
}; 



@interface YourClass : UIViewController { 
    NSInteger buttonModeAt; 
} 
@property (nonatomic) NSInteger buttonModeAt; 
-(IBAction)buttonPushedDown:(id)sender; 
-(void)tryScanForward:(id)sender; 
-(IBAction)buttonReleasedOutside:(id)sender; 
-(IBAction)buttonReleasedInside:(id)sender; 
@end 

E poi nel file .m tiro in alcune di queste cose:

@implementation YourClass 
///in your .m file 
@synthesize buttonModeAt; 


///link this to your button's touch down 
-(IBAction)buttonPushedDown:(id)sender { 
    buttonModeAt = MyButtonStalling; 
    [self performSelector:@selector(tryScanForward:) withObject:nil afterDelay:1.0]; 
} 

-(void)tryScanForward:(id)sender { 
    if (buttonModeAt == MyButtonStalling) { 
     ///the button was not released so let's start scanning 
     buttonModeAt = MyButtonScanning; 

     ////your actual scanning code or a call to it can go here 
     [self startScanForward]; 
    } 
} 

////you will link this to the button's touch up outside 
-(IBAction)buttonReleasedOutside:(id)sender { 
    if (buttonModeAt == MyButtonScanning) { 
     ///they released the button and stopped scanning forward 
     [self stopScanForward]; 
    } else if (buttonModeAt == MyButtonStalling) { 
     ///they released the button before the delay period finished 
     ///but it was outside, so we do nothing 
    } 

    self.buttonModeAt = MyButtonIdle; 
} 

////you will link this to the button's touch up inside 
-(IBAction)buttonReleasedInside:(id)sender { 
    if (buttonModeAt == MyButtonScanning) { 
     ///they released the button and stopped scanning forward 
     [self stopScanForward]; 
    } else if (buttonModeAt == MyButtonStalling) { 
     ///they released the button before the delay period finished so we skip forward 
     [self skipForward]; 
    } 

    self.buttonModeAt = MyButtonIdle; 

} 

Dopo di che basta collegare le azioni del pulsante per quello che ho Ho notato nei commenti prima delle IBactions. Non ho provato questo, ma dovrebbe funzionare.

1

provare in questo modo:

isClicked è proprietà di tipo BOOL. Impostare su YES.

- (IBAction)clickButton:(UIButton *)sender { //touch down 
    if(isClick==YES){ 
     NSLog(@"Click Button"); 
     //do all your stuffs here 
    } 
    isClick=YES; 
} 

- (IBAction)dragInsideButton:(UIButton *)sender { 
    NSLog(@"Drag Button"); 
    isClick=NO; 
} 

In cima a questo è possibile anche implementare removeTarget:Action:

Qualsiasi metodo viene chiamato prima impostato isClick = NO, mi aspetto clickButton si chiama prima in azione pulsante.

+0

Grazie! Il pulsante di selezione del pulsante attiva sempre il primo, non so come controllare. Provo entrambi, ma sempre 2 fuoco d'azione. – Alex

+0

Penso che tutte le azioni vadano in invocazione e una volta impostata non puoi fermarti. Hai provato con 'removeTarget: Action:' Sono nuovo in ios, sto ancora imparando, quindi scusa. –

+0

Grazie! Se ti piace, il mio evento touchDown si attiva solo quando fai doppio clic. – Alex

3

Questo metodo è testato e dovrebbe fare ciò che penso si stia tentando di fare. È possibile modificare il ritardo del timer per ottenere l'effetto desiderato. Ho dovuto collegare 3 azioni al pulsante per farlo funzionare - la terza azione è un touch-up che riporta il sistema alla condizione di partenza.

@interface LastViewController() 
@property (nonatomic) BOOL touchedDown; 
@property (strong,nonatomic) NSTimer *downTimer; 
@end 

@implementation LastViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.touchedDown = NO; 
} 

-(IBAction)clickDown:(id)sender { 
    self.downTimer = [NSTimer scheduledTimerWithTimeInterval:.3 target:self selector:@selector(buttonAction:) userInfo:nil repeats:NO]; 
} 

-(IBAction)dragInside:(id)sender { 
    [self.downTimer invalidate]; 
    [self buttonAction:self]; 
} 


-(void) buttonAction:(id) sender { 
    if ([sender isKindOfClass:[NSTimer class]]) { 
     self.touchedDown = YES; 
     NSLog(@"click down"); 
    }else{ 
     if (! self.touchedDown) { 
      NSLog(@"Drag"); 
     } 
    } 
} 

-(IBAction)touchUpAction:(id)sender { 
    self.touchedDown = NO; 
} 
+0

Grazie! Trascina semplicemente OK su OK. clicca, trascina di nuovo non funziona. Cosa devo fare dopo? Non so come controllare il timer. – Alex

+0

Hai implementato il metodo touchUpAction (e lo colleghi al pulsante)? Ha funzionato bene per me, su ripetuti clic e trascina. – rdelmar

+0

Grazie Signore! Il mio target touchDownAction. – Alex