Frage

Ich versuche, ein Sprungbrett-ähnliche Oberfläche in meiner App zu erstellen. Ich versuche UIButtons zu einer UIScrollView zu verwenden. Das Problem Ich laufe, um mit den Tasten keine Hand an die UIScrollView vorbei - wenn ich versuche / Dia Flick und auf den Knopf drücken, geschieht es nicht registrieren für die UIScrollView, aber wenn ich Flick den Raum zwischen Tasten, es wird funktionieren. Die Tasten klicken / funktionieren, wenn ich sie berühren.

Gibt es eine Eigenschaft oder eine Einstellung, die die Taste zwingt die Berührungsereignisse bis zu seinem übergeordneten (Superview) zu senden? Sind die Tasten etwas hinzugefügt werden müssen, sonst vor der UIScrollView hinzugefügt werden?

Hier ist mein Code:

//init scrolling area
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 480, 480)];
scrollView.contentSize = CGSizeMake(480, 1000);
scrollView.bounces = NO;
scrollView.delaysContentTouches = NO;

//create background image
UIImageView *rowsBackground = [[UIImageView alloc] initWithImage:[self scaleAndRotateImage:[UIImage imageNamed:@"mylongbackground.png"]]];
rowsBackground.userInteractionEnabled = YES;

//create button
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn.frame = CGRectMake(100, 850, 150, 150);
btn.bounds = CGRectMake(0, 0, 150.0, 150.0);
[btn setImage:[self scaleAndRotateImage:[UIImage imageNamed:@"basicbutton.png"]] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];

//add "stuff" to scrolling area
[scrollView addSubview:rowsBackground];
[scrollView addSubview:btn];

//add scrolling area to cocos2d
//this is just a UIWindow
[[[Director sharedDirector] openGLView] addSubview:scrollView];

//mem-mgmt
[rowsBackground release];
[btn release];
[scrollView release];
War es hilfreich?

Lösung

Damit UIScrollView den Unterschied zwischen einem Klick zu bestimmen, die ihren Inhalt Ansicht durchläuft (en) und einen Hauch, der in einen Streich oder Prise dreht, braucht es die Note zu verzögern und sehen, ob Sie mit dem Finger während dem bewegt hat verzögern. Durch die Einstellung delaysContentTouches zu NO in Ihrem obigen Beispiel, sind Sie dies zu verhindern, dass passiert. Daher ist vorbei die Scroll-Ansicht immer die Berührung der Taste, anstatt es zu annullieren, wenn sich herausstellt, dass der Benutzer eine Swipe-Geste ausführt. Versuchen Sie delaysContentTouches Einstellung YES.

Es könnte auch eine gute Idee, strukturell sein, hinzuzufügen, alle Ansichten auf eine gemeinsame Inhalt Ansicht in Ihrer Ansicht blättert gehostet werden und verwenden Sie nur, dass eine Ansicht wie die Subview der Ansicht blättern.

Andere Tipps

Lösung, die für mich gearbeitet enthalten:

  1. Einstellung canCancelContentTouches in UIScrollView YES.
  2. Erweiterung UIScrollView touchesShouldCancelInContentView:(UIView *)view außer Kraft zu setzen YES zurückzukehren, wenn view ein UIButton ist.

Nach Dokumentation touchesShouldCancelInContentView gibt „YES weitere Touch-Nachrichten zu löschen, um zu sehen, NO Blick zu haben, weiterhin diese Nachrichten empfangen Der Standardrückgabewert YES ist, wenn die Ansicht nicht ein UIControl Objekt ist, andernfalls es NO zurückgibt.“

Da UIButton ein UIControl ist die Erweiterung notwendig ist, erhalten canCancelContentTouches zu übernehmen, die Scrollen ermöglicht.

Ich habe einen ähnlichen Fall, dass eine Reihe von Tasten auf einem UIScrollView, und ich möchte diese Tasten scrollen. Am Anfang subclassed ich beide UIScrollView und UIButton. Allerdings habe ich bemerkt, dass mein subclassed UIScrollView nicht touchesEnded Ereignis erhalten, also habe ich nur Unterklasse UIButton.


@interface MyPhotoButton : UIButton {
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end

@implementation MyPhotoButton

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [self setEnabled:NO];
    [self setSelected:NO];
}

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

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    [self setEnabled:YES];
}

@end

UIScrollView behandelt viele Ereignisse selbst. Sie müssen touchesDidEnd zu handhaben und schlagen Test für Schaltflächen innerhalb der UIScrollView manuell.

OK hier ist die Antwort:

Unterklasse UIButton. (ANMERKUNG: Tel. [Super ....] zu Beginn jeder Überschreibung

  • eine Eigenschaft hinzufügen. Ein vom Typ BOOL (Genannt enableToRestore)
  • eine Eigenschaft hinzufügen. Ein vom Typ CGPoint (Genannt startTouchPosition)
  • in der awakeFromNib und Initwithframe, stellen die enableToRestore zum isEnabled Eigenschaft)
  • außer Kraft setzen "touchesBegan: withevent:" den Beginn der Note zu speichern Position.
  • außer Kraft setzen "touchesMoved: withevent:" zu überprüfen, um zu sehen, ob es horizontal ist Bewegung.
  • Wenn YES, aktiviert NO und ausgewählt NO.

Beispielcode:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *touch = [touches anyObject];

    [super touchesBegan:touches withEvent:event];
    [self setStartTouchPosition:[touch locationInView:self]];
}


//
// Helper Function
//
- (BOOL)isTouchMovingHorizontally:(UITouch *)touch 
{
    CGPoint currentTouchPosition = [touch locationInView:self];
    BOOL      rValue = NO;

    if (fabsf([self startTouchPosition].x - currentTouchPosition.x) >= 2.0) 
    {
        rValue = YES;
    }

    return (rValue);
}

//
// This is called when the finger is moved.  If the result is a left or right
// movement, the button will disable resulting in the UIScrollView being the
// next responder.  The parrent ScrollView will then re-enable the button
// when the finger event is ended of cancelled.
//
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesMoved:touches withEvent:event];
    if ([self isTouchMovingHorizontally:[touches anyObject]]) 
    {
        [self setEnabled:NO];
        [self setSelected:NO];
    } 
}

Dies wird die UIScrollView aktiviert.

Unterklasse UIScrollView. (ANMERKUNG: Tel. [Super ....] zu Beginn jeder Überschreibung

  • Ignoriere beide "touchesEnded: withevent:" und "touchesCancelled: withevent:"
  • In der Überschreibung, setzen Sie alle Subviews (und ihre Subviews) aktiviert Flagge.
  • Hinweis: eine Kategorie verwenden und die Methode zu UIView hinzufügen:

.

- (void) restoreAllEnables
{
    NSArray   *views = [self subviews];

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

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

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [self restoreAllEnables];
}
  • In der Kategorie:

.

-(void) restoreEnable
{
    NSArray   *views = [self subviews];

    if ([self respondsToSelector:@selector(enableToRestore)])
    {
        [self setEnabled:[self enableToRestore]];
    }

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

EDIT Hinweis: Ich habe nie 3 Arbeit Antwort. Ebenso: die setDelaysContentTouches: NEIN (im View-Controller oder irgendwo festgelegt) ist für die besten Ergebnisse auf Antwort eingestellt werden 4. Dies ermöglicht sehr schnelle Reaktion auf die Tasten. Einstellen setDelaysContentTouches: JA setzt gravierende Auswirkungen (150ms) auf Reaktionszeit auf die Tasten und macht Licht, berühren schnell nicht möglich

.

Eine andere Möglichkeit ist:
1. Ersatz de Taste durch eine einfache benutzerdefinierte UIView
2. Setzen Sie das Flag "userInterationEnable = yes;" auf der init-Methode
3. Nach Ansicht der UIResponder Methode überschreiben „touchesEnded“ Hier können Sie die Aktion auslösen Sie wie eine Schaltfläche müssen.

Nach meiner Erfahrung der erste Antwort, das heißt, einfach delaysContentTouches Einstellung YES nichts in Bezug auf das Problem ändern. Die Tasten werden immer noch nicht Tracking-Ergebnisse auf die Scroll-Ansicht liefern. Die dritte Antwort ist einfach und sehr brauchbar. Dank sieroaoj!

Doch für die dritte Antwort, die Sie auch delaysContentTouches auf YES gesetzt arbeiten müssen. Ansonsten wird das Verfahren touchesEnded auch für die Verfolgung innerhalb der Ansicht aufgerufen werden. Deshalb konnte ich das Problem lösen, indem sie:

  
      
  1. Ersatz de Taste durch eine einfache benutzerdefinierte UIView
  2.   
  3. Setzen Sie das Flag "userInterationEnable = yes;" auf der init-Methode
  4.   
  5. In der Ansicht überschreibt die UIResponder Methode „touchesEnded“ hier   Sie können die Aktion auslösen Sie
  6.   

Vierter. Satz delaysContentTouches YES

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top