2013-04-30 10 views
8

Cóż, myślę, że najlepiej jest pokazać, co mam na myśli:Co się dzieje z wielkością obszaru uderzenia przeciągnij/zakończ Uibutton?

Animation of a UIButton reacting to dragging motions

można wyraźnie zobaczyć, że raz mamy dotknął przycisku i przeniósł się z niego, w konsekwencji zdarzenia ruch w wyzwala zmiana stanu przycisku z daleka.

Chociaż to zachowanie jest naturalne dla wszystkich UIButtonów, nie mogłem go rozwiązać za pomocą rozwiązania Google.

Czy istnieje sposób na zmniejszenie obszaru trafienia dla tego typu czułości UIBUTTON? Chcę go zmniejszyć, ponieważ czuję, że przycisk jest wystarczająco duży, jak to jest, i zapewni lepsze wrażenia użytkownika wraz z efektami dźwiękowymi góra/dół.

UPD: Poniższy kod override dla UIButton został opublikowany w another thread:

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGFloat boundsExtension = 25.0f; 
    CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension); 

    BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:self]); 
    if(touchOutside) 
    { 
     BOOL previousTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]); 
     if(previousTouchInside) 
     { 
      NSLog(@"Sending UIControlEventTouchDragExit"); 
      [self sendActionsForControlEvents:UIControlEventTouchDragExit]; 
     } 
     else 
     { 
      NSLog(@"Sending UIControlEventTouchDragOutside"); 
      [self sendActionsForControlEvents:UIControlEventTouchDragOutside]; 
     } 
    } 
    return [super continueTrackingWithTouch:touch withEvent:event]; 
} 

To zmienia rozszerzenie obszaru hit używany przez Drag W/wywlec wydarzenia, jeszcze przycisk W górę/W dół stany przełączania dokładnie w taki sam sposób jak wcześniej.

+1

wydaje się duplikatu tego pytania: http://stackoverflow.com/questions/14340122/uicontroleventtouchdragexit-triggers-when-100-pixels-away- from-uibutton –

+1

Tak, prawie, ale podana tam odpowiedź nie zmienia stanu przycisku Up/Down. Wydaje się, że zależą one od czegoś innego z rozszerzeniem obszaru trafień 100.0f. – Kai

Odpowiedz

1

Nie wiem, czy nadal masz ten sam problem, ale udało mi się go naprawić, używając podobnego kodu w metodzie touchEnded: withEvent:.

Zmieniłem także tę metodę, aby dodać touchEnter i dragInside, ponieważ przy bieżącym kodzie te zdarzenia nadal używały tych samych granic. Dodatkowo kazałem każdej ze skrzynek zwrócić TAK, aby super nie było wywoływane (spowodowałoby to przedwczesne wywołanie przeciągnięcia wewnątrz).

Oto ostateczny kod, który skończyło się w dwóch metodach:

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGFloat boundsExtension = 25.0f; 
    CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension); 

    BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:self]); 
    if(touchOutside) { 
     BOOL previousTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]); 
     if(previousTouchInside) { 
      [self sendActionsForControlEvents:UIControlEventTouchDragExit]; 
      return YES; 
     } 
     else 
     { 
      [self sendActionsForControlEvents:UIControlEventTouchDragOutside]; 
      return YES; 
     } 
    } 
    else { 
     BOOL previousTouchOutside = !CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]); 
     if (previousTouchOutside) { 
      [self sendActionsForControlEvents:UIControlEventTouchDragEnter]; 
      return YES; 
     } 
     else { 
      [self sendActionsForControlEvents:UIControlEventTouchDragInside]; 
      return YES; 
     } 
    } 
    return [super continueTrackingWithTouch:touch withEvent:event]; 
} 


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    CGFloat boundsExtension = 25.0f; 
    CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension); 

    BOOL touchInside = CGRectContainsPoint(outerBounds, [touch locationInView:self]); 
    if (touchInside) { 
     return [self sendActionsForControlEvents:UIControlEventTouchUpInside]; 
    } 
    else { 
     return [self sendActionsForControlEvents:UIControlEventTouchUpOutside]; 
    } 
    return [super endTrackingWithTouch:touch withEvent:event]; 
} 

UWAGA: Zwrot Super sposobu na końcu nie jest konieczne, ale zostawiłem go tam dla kompletności. Wersja

2

Swift:

private let _boundsExtension: CGFloat = 0 // Adjust this as needed 

    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool { 
    let outerBounds: CGRect = CGRectInset(bounds, -1 * _boundsExtension, -1 * _boundsExtension) 
    let currentLocation: CGPoint = touch.locationInView(self) 
    let previousLocation: CGPoint = touch.previousLocationInView(self) 

    let touchOutside: Bool = !CGRectContainsPoint(outerBounds, currentLocation) 
    if touchOutside { 
     let previousTouchInside: Bool = CGRectContainsPoint(outerBounds, previousLocation) 
     if previousTouchInside { 
     sendActionsForControlEvents(.TouchDragExit) 
     } else { 
     sendActionsForControlEvents(.TouchDragOutside) 
     } 
    } else { 
     let previousTouchOutside: Bool = !CGRectContainsPoint(outerBounds, previousLocation) 
     if previousTouchOutside { 
     sendActionsForControlEvents(.TouchDragEnter) 
     } else { 
     sendActionsForControlEvents(.TouchDragInside) 
     } 
    } 

    return true 
    } 

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    let touch: UITouch = touches.first! 
    let outerBounds: CGRect = CGRectInset(bounds, -1 * _boundsExtension, -1 * _boundsExtension) 
    let currentLocation: CGPoint = touch.locationInView(self) 

    let touchInside: Bool = CGRectContainsPoint(outerBounds, currentLocation) 
    if touchInside { 
     return sendActionsForControlEvents(.TouchUpInside) 
    } else { 
     return sendActionsForControlEvents(.TouchUpOutside) 
    } 
    } 
Powiązane problemy