2009-03-25 23 views
8

Chcę móc obiekt interfejsu użytkownika podobny do UIImageView i wstawić wewnątrz niego obraz.Jak mogę użyć CGContextDrawTiledImage do płytek obrazu?

Byłem w stanie użyć CGContextDrawTiledImage do aktualizacji tła w oknie głównym, ale nie widoku obrazu. Mogę to zrobić, jeśli zmodyfikuję funkcję drawRect wewnątrz klasy MainView.

Czuję, że jestem blisko, ale nadal czegoś brakuje. Czy ktoś może wskazać mi właściwy kierunek?

- (void)drawRect:(CGRect)rect { 

CGImageRef image = CGImageRetain(currentImage.CGImage); 

CGRect imageRect; 
imageRect.origin = CGPointMake(160, 240); 
imageRect.size = CGSizeMake(320.0, 480.0); 

CGContextRef uiContext = UIGraphicsGetCurrentContext(); 

CGContextClipToRect(uiContext, CGRectMake(0.0, 0.0, rect.size.width, rect.size.height)); 

CGContextDrawTiledImage(uiContext, imageRect, image); 

}

+1

To jest bardzo stare pytanie, wiem: na wszelki wypadek, jeśli ktoś się tu potknie: nie powinieneś przesłonić drawRect z UIImageView - myślę, że to jedyna podklasa UIView w UIKit z tym ograniczeniem ... –

Odpowiedz

17

Powiedzmy masz CGImageRef dla obrazu chcesz dachówki zwanej tileImage i UIImageView nazwie imageView. Musisz utworzyć UIImage, aby przypisać do właściwości image z imageView. Można to zrobić tak:

CGSize imageViewSize = imageView.bounds.size; 
UIGraphicsBeginImageContext(imageViewSize); 
CGContextRef imageContext = UIGraphicsGetCurrentContext(); 
CGContextDrawTiledImage(imageContext, (CGRect){ CGPointZero, imageViewSize }, tileImage); 
UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

imageView.image = finishedImage; 

Spowoduje to utworzenie kontekstu bitmapy obrazu pożądanej wielkości, dachówka obraz w tym kontekście uzyskać UIImage z kontekstu, a następnie przypisać go do UIImageView. Możesz naprawdę umieścić ten kod w dowolnym miejscu, dopóki widok obrazu i obraz płytki są załadowane i gotowe do pracy.

2

Zamiast próbować modyfikować UIImageView rozważyć instacji UIView zamiast. UIImageView jest specjalnie zaprojektowany do wyświetlania jednego obrazu bez kafelków, a niektóre z nich mogą Cię denerwować. To naprawdę nie ma być modyfikowane w sposób, w jaki opisujesz.

W podklasie UIView (UITiledImageView?) Możesz użyć metody drawRect: do zrobienia tego, co chcesz. Możesz nawet tworzyć ivars dla obrazu, jego wielkości i właściwości płytek, co zapewnia większą elastyczność i rozszerzalność.

Aktualizacja z przykładowego projektu: http://github.com/kailoa/6tringle-tiledimageview/tree/master

Odpowiedni kod rysunek:

- (void)drawRect:(CGRect)rect 
{ 
    if (TiledImage) { 

     //Since we are retaining the image, we append with ret_ref. this reminds us to release at a later date. 
     CGImageRef image_to_tile_ret_ref = CGImageRetain(TiledImage.CGImage); 

     CGRect image_rect; 
     image_rect.size = TiledImage.size; //This sets the tile to the native size of the image. Change this value to adjust the size of an indivitual "tile." 

     CGContextRef context = UIGraphicsGetCurrentContext(); 

     CGContextDrawTiledImage(context, image_rect, image_to_tile_ret_ref); 

     CGImageRelease(image_to_tile_ret_ref); 
    } 
} 
0

Niedawno zrobił to poprzez tworzenie niestandardowych UIView.

@interface TiledImageView : UIView { 
@private 
    UIImage *image_; 
} 

@property (nonatomic, retain) UIImage *image; 
@end 

i dla pliku .m:

@implementation TiledImageView 
@synthesize image = image_; 

- (void)dealloc { 
    [image_ release]; 
    [super dealloc]; 
} 

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     // Initialization code 
     self.image = [UIImage imageNamed:@"BGTile.png"]; 

    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect { 
    // Drawing code 
    CGImageRef image = CGImageRetain(image_.CGImage); 

    CGRect imageRect; 
    imageRect.origin = CGPointMake(0.0, 0.0); 
    imageRect.size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextClipToRect(context, CGRectMake(0.0, 0.0, rect.size.width, rect.size.height)); 
    CGContextDrawTiledImage(context, imageRect, image); 
    CGImageRelease(image); 
} 

@end 
26

Jeśli chcesz po prostu płytki obraz w widoku, zmienić go do normalnego UIView i płytek tle z UIColor initWithPatternImage:

backgroundView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageWithContentsOfFile:[self bundlePath:@"some_tile_image.png" inDirectory:@"tiles"]]]; 
+2

Chciałbym użyć - [UIImage imageNamed:] tutaj, ale tak, ten sam pomysł. Myślę, że można również zmienić offset, ale nie pamiętam dokładnie. –

+1

Ten jest doskonały. To dziwne, że iOS pozwala obrazowi być UIColor, ale cokolwiek. – jakeboxer

+16

To przeciekłoby. Użyj tego 'backgroundView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @" some_tile_image.png "]];' –

1

Przepraszamy za nie wiedząc, jak komentować nawzajem odpowiedzi, więc Stworzyłem nową odpowiedź tutaj:

Chciałbym tylko wskazać, że odpowiedź dostarczona przez Kailoa Kadano ma błąd, image_rect.origin nie jest poprawnie zainicjalizowany.

Około 3 tygodnie temu skopiowałem jego kod do mojego projektu i wygląda na to, że działa. Jednak wczoraj próbowałem uruchomić kod w symulatorze ios (iphone 4.3), po prostu zawiesił się w CGContextDrawTiledImage. Po dodaniu następujący wiersz jak pokazano w odpowiedzi keremk za:

image_rect.origin = CGPointMake(0.0, 0.0); 

to znowu działa!

To dość podchwytliwe, właściwie na początku testowałem pod symulatorem iPhone 4.3, a ostatnio testowałem pod symulatorem iphone 4.0, a następnie wczoraj, kiedy wróciłem do symulatora 4.3 lub 4.2, pojawia się problem. To jest image_rect.origin jest niezdefiniowane, czasami jest to zero danych, może czasami ma pewne losowe dane.

Powiązane problemy