UIScrollView mit UIButtons - wie Springboard neu erstellen?
-
19-08-2019 - |
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];
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:
- Einstellung
canCancelContentTouches
inUIScrollView
YES
. - Erweiterung
UIScrollView
touchesShouldCancelInContentView:(UIView *)view
außer Kraft zu setzenYES
zurückzukehren, wennview
einUIButton
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:
- Ersatz de Taste durch eine einfache benutzerdefinierte UIView
- Setzen Sie das Flag "userInterationEnable = yes;" auf der init-Methode
- In der Ansicht überschreibt die UIResponder Methode „touchesEnded“ hier Sie können die Aktion auslösen Sie
Vierter. Satz delaysContentTouches
YES