{ radak.org }         just another (tech) blog

13Feb/107

iPhone segédlet 2: érintés feldolgozása, kép mentése

Ez a segédlet az idő hiánya miatt inkább csak felsorolás szintű lesz, viszont az lesz benne, amit a legtöbben kérdeztek eddig:
- képernyő érintésének lekezelése (touchesBegan, touchesMoved, touchesEnded)
- kép lementése a Camera Roll -ba (UIImageWriteToSavedPhotosAlbum, drawRect)

1. A képernyő érintése (A kódot UIViewController-ben kell elhelyezni!)

    Az iPhone (és persze a Touch) készülékek multi touch-osak, ez azt jelenti, hogy egyszerre több érintési pontot is le tudnak kezelni.
    Legtöbbször elég csak az első érintéssel foglalkoznunk, most így is fogom bemutatni, viszont a minta kódrészletek alapján egyszerű lesz átírni a multi funkcióra.
    Alapvetően három fontos esemény van, amivel érdemes foglalkozni:
    touchesBegan: az érintés kezdete
    Ez az esemény akkor következik be, amikor hozzáérünk a kijelzőhöz.
    touchesMoved: a képernyőn az ujjunk mozgása
    Ez egy folyamatosan frissülő esemény, amikor a képernyőn mozgatjuk az ujjunkat.
    (Itt érdemes meggondolni, hogy milyen mintavételezéssel futtatjuk a touchesMoved-ban elhelyezett kódot, illetve hogy minél rövidebb kódot használjunk!)
    touchesEnded: az érintés vége
    Ez az esemény akkor következik be, ha elengedjük a kijelzőt.
    Ha csak egy pillanatra rábökünk a kijelzőre, akkor is a touchesBegan után ez az esemény mindig bekövetkezik!
    (Én azt tapasztaltam, hogy ha rá kell kattintani valamire és nem sikerül elsőre eltalálni, akkor az emberek többsége a ujj mozgtásával megkeresik a megfelelő pontot és ott engedik el a kijelzőt, ezért érdemes itt feldolgozni minden olyan eseményt, ami csak egy egyszerű kattintásnak felel meg!)

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      NSSet *allTouches = [event allTouches]; // az összes érintés egy tömbben
      UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; // az első érintés
      CGPoint p = [touch locationInView:[self view]]; // az érintés koordinátái
      NSLog(@"A kezdeti koordináták: %f, %f ", p.x, p.y);
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
      NSSet *allTouches = [event allTouches]; // az összes érintés egy tömbben
      UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; // az első érintés
      CGPoint p = [touch locationInView:[self view]]; // az érintés koordinátái
      NSLog(@"Mozgás közben az aktuális koordináták: %f, %f ", p.x, p.y);
    }
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
      NSSet *allTouches = [event allTouches]; // az összes érintés egy tömbben
      UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; // az első érintés
      CGPoint p = [touch locationInView:[self view]]; // az érintés koordinátái
      NSLog(@"Itt engedtem el a kijelzőt: %f, %f ", p.x, p.y);
    }

2. Kép mentése (A kódot UIView-ban kell elhelyezni!)

    Második AppStore-os programom az iPaint volt, amiben a megrajzolt képet ki lehet menteni a kamera albumba.
    A kimetés elég egyszerű, csak arra kell vigyázni, hogy a képet mentés előtt el kell forgatni, mert különben a bitmap fejjel lefelé fog bekerülni az albumba!
    Itt egy kicsit átírt kivonat az iPaint-ből, szerintem a kommentek elég beszédesek:

    - (void)drawRect:(CGRect)rect {
    	CGFloat _Color[4] = { 255,0,0,1 }; // piros szín
    	CGMutablePathRef path = CGPathCreateMutable(); // ebben a path-ban tároljuk a megjelenítendő vonalakat, pontokat
    	CGContextRef context = UIGraphicsGetCurrentContext(); // az aktuális rajz felület lekérdezése (alap esetben teljes képernyő)
     
    	// kép elforgatása, hogy a camera roll-ban jó legyen
    	// ezt akkor kell megtenni, ha lementjuk a képet, különben egy if-et tegyünk elé és ne forgassuk, mert a kijelzőn is megfordul!
    	CGContextTranslateCTM(context, 0, self.bounds.size.height);
    	CGContextScaleCTM(context, 1.0, -1.0);	
     
    	// felveszünk egy 3 pixel vastagságú piros vonalat
    	CGContextSetLineWidth(context, 3.0);
    	CGContextSetStrokeColor(context, _Color);
    	CGPathMoveToPoint(path, nil, 5.0, 5.0);
    	CGPathAddLineToPoint(path, nil, 100.0, 100.0);
    	CGContextAddPath(context, path);
    	// kirajzoljuk a képernyőre a path tartalmát (most a piros vonal van benne)
    	CGContextStrokePath(context);
     
    	// elmentjük a képet
    	UIGraphicsBeginImageContext(self.bounds.size);
    	CGImageRef vImageRef = CGBitmapContextCreateImage(context);
    	CGContextDrawImage(UIGraphicsGetCurrentContext(), self.bounds, vImageRef);
    	UIImage *activeImage = UIGraphicsGetImageFromCurrentImageContext();
    	UIGraphicsEndImageContext();
    	// a saveEnded saját függvény, a mentés végén meghívjuk
    	UIImageWriteToSavedPhotosAlbum(activeImage, self, @selector(saveEnded:didFinishSavingWithError: contextInfo:) , nil);
     
    	CGContextFlush(context);
    }
     
    -(void)saveEnded:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo; {
    	// Ez akkor fut le, ha a mentés véget ért.
    	// Az error-ban megkapjuk, ha valami hiba történt.
    	// Itt érdemes értesíteni a felhasználót, hogy vége a mentésnek és itt érdemes törölni a képernyőt is!
    }

Legközelebb a Shake, a Status Bar és a levél küldése lesz a téma!

Comments (7) Trackbacks (0)
  1. Hello!

    Pár napja keresgélek egy egyszerű dologra megoldást.
    Van egy UiTextView, aminek a backgroundja egy kép és szeretném eltolni a benne lévő szöveget, gyakorlatilag egy leftmargin beállítás kellene, de sehol sem találok értelmeset, ami nem tolná el a képet is (setcontent). Van erre megoldás ? Nagyon gányolásnak érezném, ha a textView mögé kellene raknom egy képet, ami a háttér lenne, hiszem akkor az nem scrollozódna, nem lenne annyira szép a dolog. Előre is köszönöm a választ.

    Ottó

  2. Olyanra gondolsz, mint ami az iTinker tetején van?
    Oda egy UIButton-t helyeztem el, és annak a centerjét mozgatom egy NSTimer-rel:

    - (void)viewDidLoad {
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(adScroll) userInfo:nil repeats:YES];
    }

    - (void)adScroll {
    adBtn.center = CGPointMake((adBtn.center.x – 5), adBtn.center.y);
    if (adBtn.center.x < -90) adBtn.center = CGPointMake(320 + 90, adBtn.center.y);
    }

  3. Nem teljesen, adott egy szélességében teljes képet kitöltő UITextView, ebbe iratom ki az adatbázisban lévő adatok egy részét, de megadtam neki egy hátteret, ami elvesz a hasznos területből, bal oldalról körülbelül10 pixelnyit. Ennyivel kellene eltolnom a textViewben lévő szöveget.

    Itt a kép az APPról, ( http://m.blog.hu/de/demotivacio/image/radak/helpme.jpg )
    Mint látható az a fránya szöveg rámászik a “papír kivágott részére”, ezt szeretném elkerülni anélül, hogy felesleges elemeket kelljen beépíteni.

  4. Esetleg az uitextview.contentInset = UIEdgeInsetsMake(10,0,0,0); ?

  5. Próbáltam, de egyik paraméterrel sem tolta el a megfelelő tengelyen. Valamiért csak az Y tegnelyen mozdult el a szöveg. contentInset-et ezután próbáltam Builderből állítani akkor viszont magát a képet is nyújtotta, viszont lehet +10-el paramétereztem hibásan, ha hazaérek ezt újra megpróbálom, mert ez volt az egyetlen megoldás amivel ténylegesen csak a szöveget sikerült befolyásolnom, viszont mint mondtam valamiért csak függőleges eltolást tudtam kicsikarni.

  6. Sajnos jól csináltam múltkor is, ez csak függőlegesen tolja lejjebb a szöveget, a margint el tudja tűntetni a negatív paraméterezése, de semmilyen paraméterrel sem tudom megtoldani.
    self.textView.contentInset = UIEdgeInsetsMake(100,0,0,0);
    pl letolja nekem a szöveget 100 pixellel.


Leave a comment


No trackbacks yet.