• Das kreative Thema des Monats Oktober wird vor allem diejenigen unter Euch besonders ansprechen, denen Do-it-yourself quasi im Blut liegt. Zeigt uns Eure Improvisationskünste oder fotografiert, was andere Leute sich so im Alltag zusammengestrickt haben. --> Zum Mitmachen bitte hier klicken

Long Press

branco145

Rheinischer Winterrambour
Registriert
26.07.09
Beiträge
933
Ich hab bisher einen Long Press so realisiert:

Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
	NSLog(@"touch began");
	[self performSelector:@selector(longTap) withObject:nil afterDelay:0.5];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	NSLog(@"touch ended");
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
											 selector:@selector(longTap) object:nil];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
	NSLog(@"touches moved");
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
											 selector:@selector(longTap) object:nil];
}

-(void) longTap 
{
//Tu was
}

Wie kann ich aber auch einen "Long Press" ermitteln der irgendwo auf der View (z.B NavBar, Button, Table) stattfindet, wie auf dem aktuellem iPod nano?
 
Ich hab wohl keine Ahnung wie das beim aktuellen iPod Nano ist,
aber du hast doch bei den obigen Methoden immer die Touches als Parameter.
Jeder dieser UITouch Objekte liefert dir die aktuelle Position zurück.
 
Also jeder Touch hat einen Start oder ein Ende.

Das Ende kann canceled oder finished sein.
Du bekommst es also in jedem Fall mit.


Ich würde mir spontan ein paar Instanzvariablen erstellen in der Klasse wo es benötigt wird.
Einmal ein NSDate mit dem Zeitpunkt an dem der Touch startete, ein CGPoint für die Startposition und ein Bool der aussagt ob "longPress" aktiv ist.

Wenn ein neues Touchevent startet würde ich alles 3 setzen und einen call an super machen.
Ausserdem mit perform selector after delay (mit 0.5 - 1.0 Sekunden rum?) dein long tap aufrufen.

Bei Touch Moved testen wie weit die neue Position vom Startpunkt weg ist.
Ist sie nahe genug um nicht als Bewegung zu gelten und der Bool noch gesetzt, kein call an super.
Ist zu weit weg um noch als "long press" zu gelten den Bool zurücksetzen und call an super, damit andere Gesten (wie z.B: swipes) vom System entsprechend verarbeitet werden.

Bei Touch canceled den Bool rücksetzen, call an super.

Bei Touch Finished abfragen ob der Touch länger gedauert hat als die 0.5 - 1.0 Sekunden.
Wenn ja, kein call an super (Es soll statt der normalen Click Methode ja deine LongTap Methode etwas tun),
Wenn nein, Bool rücksetzen & call an super

In deiner LongTap Methode, welche Zeitverzögert aufgerufen wird,
testest du nun ob der Bool noch aktiv ist.
Sprich ob der Touch nicht vorzeitig beendet wurde, z.B. durch eine Swipe Geste oder weil der Finger nicht lang genug auf dem Display war.

Wenn er noch aktiv war, setze ihn zurück und führe aus was immer bei einem long Tap passieren soll.
Anhand des CGPoints kannst du ggf. noch abhängig von der Position innerhalb der View unterschiedliche Aktionen ausführen.


Dies ist ungetestet und nicht lange durchdacht.
Kann also sein das noch ein paar Dinge mehr beachtet werden müssen.
 
Hrhr, hab deinen Anfangspost wohl total falsch gelesen.

Deine Antwort hast dir an sich doch schon selbst gegeben.
Die von dir genannten Elemente sind doch alle von UIView abgeleitet und sollten somit wie am Anfang von dir beschrieben auch dort funktionieren.

Nur musst du an den richtigen Stellen, wie ein meinem letzten Post erwähnt, den call an super durchgereihen.
Sonst ist natürlich Sense mit der normalen Funktionalität der Elemente.
 
Gibt's da vielleicht einen einfacheren Beispielcode? Im Grunde soll er ja nur wissen, wenn IRGENDWO auf der View, sei es ein Button, eine TableView etc. ein langer Touch gemacht wird. Und nicht nur auf einer freien Fläche, wo man die View direkt berühren kann.

Sowas:
http://www.youtube.com/watch?v=RrD2Qe_BsVo
Ab 04:06

Also z.B auch auf einer TableView
 
Zuletzt bearbeitet:
Hab mir jetzt eine Custom Table Cell erstellt und darin das Event ausführen lassen. Funktioniert auch, nur wie öffne ich aus z.B TableViewCell.m heraus eine neue View?

Da ich für die View eine spezielle Animation habe sieht der Code normalerweise so aus:
Code:
BwA_4ViewController *menu = [[BwA_4ViewController alloc] initWithNibName:nil bundle:nil];
	CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0.0, 20.0);
	[[menu view] setTransform:myTransform];
		// Hier ist der wichtige Teil
UIView *currentView = ??????.view;
UIView *theWindow = [currentView superview];
	UIView *newView = menu.view; 
	[currentView removeFromSuperview];
	[self addSubview:newView];
	CATransition *animation = [CATransition animation];
	[animation setDuration:0.5];
	[animation setType:kCATransitionPush];
	[animation setSubtype:kCATransitionFromBottom];
	[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
	[[theWindow layer] addAnimation:animation forKey:@"SwitchToView1"];

Wie komm ich jetzt von der TableCell an die View auf der die TableView liegt?
 
Gib deiner Cell doch eine Instanzvariable "viewController" und setzte diese in cellForRowAtIndexpath mit
cell.viewController = self;

Dem viewController dann eine Methode verpassen die die gewünschte Aktion ausführt.
Dann kannst in der Cell beim Long Press [self.viewController doSomething]; ausführen.
 
Wie komm ich jetzt von der TableCell an die View auf der die TableView liegt?
Geh die View-Hierarchie nach oben. Sowas hier sollte gehen
Code:
UIView *container = self.view;
while(container)
{
	if([container isKindOfClass:[UITableView class]])
	{
		container = [container superview];
		break;
	}
		
	container = [container superview];
}

Von der Idee meines Vorposters würde ich abraten, unnötige Platzverschwendung. Wenn du an den aktuellen view controller willst, setz dir irgendwo nen static pointer der auf den aktuellen zeigt. Es ist immer nur ein view controller sichtbar, also brauchts auch nur einen Pointer! In deinen Controllern überschreibst du dann
Code:
- viewDidAppear:(BOOL)
bzw
Code:
-viewWillAppear:(BOOL)
und setzt da die Variable auf self.