9 April 2010

Создание полосы прокрутки картинок а-ля iPhoto. Часть 1

Development for iOS
Translation
Original author: MLS-Automatization
Начав программировать под iPad, я не нашёл компонента, подобного полосе прокрутки в приложении iPhoto для iPad.
image
Я попробовал реализовать что-то подобное.



Сначала, создадим ImageScrubberToolbar, который унаследуем от UIToolbar.
@interface ImageScrubberToolbar : UIToolbar
{
IBOutlet id<ImageScrubberToolbarDelegate> delegate;
NSArray * imagesArray;
NSMutableArray * imageViewsArray;
UIImageView * selectionImageView;
}
@property (nonatomic, retain) id<ImageScrubberToolbarDelegate> delegate;
-(void) setImagesArray:(NSArray *) array;
@end


* This source code was highlighted with Source Code Highlighter.



Теперь добавим private-методы ImageScrubberToolbar в m-файл.
@interface ImageScrubberToolbar()
-(int) checkTouchPosition:(CGPoint) aPoint;
-(void) slideSelection:(CGPoint) aTouchPoint;
-(float) leftMargin;
-(float) rightMargin;
@end


* This source code was highlighted with Source Code Highlighter.



Опишем протокол делегата для реакции на событие выбора изображения.
@protocol ImageScrubberToolbarDelegate
-(void)imageSelected:(int) anIndex;
@end


* This source code was highlighted with Source Code Highlighter.



В метод – (id)initWithCoder:(NSCoder *)aDecoder мы добавим кастомную инициализацию.
// Custom initialization
imageViewsArray = [[NSMutableArray alloc] init];

//setting custom height
[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y - 36, self.frame.size.width, 80)];

//setting image for selection
UIImage * img = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] resourcePath],@"selection.png"]];

selectionImageView = [[UIImageView alloc] initWithImage:img];
[self addSubview:selectionImageView];


* This source code was highlighted with Source Code Highlighter.



Теперь реализуем метод -(void) setImagesArray:(NSArray *) array для задания массива отображаемых картинок.
if (imagesArray != array)
{
//release old array of images
[imagesArray release];

//remove old image views
for (UIImageView * v in imageViewsArray)
{
[v removeFromSuperview];
}
[imageViewsArray removeAllObjects];

//set new array of images
imagesArray = [array retain];

//calculate margins
float leftMargin = [self leftMargin];
float topMargin = (self.frame.size.height - SMALL_SIZE)/2.f;

for (int i=0; i<[imagesArray count]; i++)
{
UIImage * img = [imagesArray objectAtIndex:i];

//create new image view
UIImageView * imgView = [[UIImageView alloc] initWithImage:img];
[imageViewsArray addObject:imgView];
[self addSubview:imgView];

//disallow user interaction with image view
imgView.userInteractionEnabled = NO;

//set position
imgView.frame = CGRectMake(leftMargin + SMALL_SIZE*i,
topMargin,
SMALL_SIZE,
SMALL_SIZE);
}
[selectionImageView setFrame:CGRectMake(leftMargin, 0, SMALL_SIZE, LARGE_SIZE)];
}


* This source code was highlighted with Source Code Highlighter.



Следующий шаг — реализация методов для проверки точки касания и сдвига окошка выбора.
-(int) checkTouchPosition:(CGPoint) aPoint
{
float leftMargin = [self leftMargin];
// float topMargin = (self.frame.size.height - SMALL_SIZE)/2.f;

return (aPoint.x - leftMargin)/SMALL_SIZE;
}

-(void) slideSelection:(CGPoint) aTouchPoint
{
float x_min = [self leftMargin] - SMALL_SIZE/2.f;

if (aTouchPoint.x < x_min)
{
return;
}
int pos = [self checkTouchPosition:aTouchPoint];

if (pos > [imagesArray count] - 1)
{
return;
}

float x_pos = aTouchPoint.x - SMALL_SIZE/2.f;

if (x_pos < x_min)
{
x_pos = x_min;
}
else
{
float x_max = [self rightMargin] - SMALL_SIZE/2.f;
if (x_pos > x_max)
{
x_pos = x_max;
}
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:ANIMATION_DURATION];

[selectionImageView setFrame:CGRectMake(x_pos,
0,
SMALL_SIZE,
LARGE_SIZE)];

[UIView commitAnimations];
}


* This source code was highlighted with Source Code Highlighter.



Для обработки событий касания добавьте следующий код.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1)
{
return;
}

UITouch * touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[self slideSelection:p];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1)
{
return;
}

UITouch * touch = [touches anyObject];
CGPoint p = [touch locationInView:self];

[self slideSelection:p];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1)
{
return;
}

UITouch * touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
int pos = [self checkTouchPosition:p];

if (pos < 0)
{
pos = 0;
}
else if (pos > [imagesArray count] - 1)
{
pos = [imagesArray count] - 1;
}

float leftMargin = [self leftMargin];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:ANIMATION_DURATION];

[selectionImageView setFrame:CGRectMake(leftMargin + SMALL_SIZE*pos,
0,
SMALL_SIZE,
LARGE_SIZE)];
[UIView commitAnimations];
[delegate imageSelected:pos];
}


* This source code was highlighted with Source Code Highlighter.



Следующие шаги — добавление ImageScrubberToolbarDelegate в реализуемые нашим Application Delegate протоколы, добавление outlet'a ImageScrubberToolbar в члены Application Delegate и реализация метода -(void)imageSelected:(int) anIndex .
Итак, мы реализовали все главные классы и методы.

Наш ImageScrubberToolbar будет выглядеть так —
image

Вы можете скачать исходный код проекта ImageScrubber.
Продолжение смотрите здесь
Tags:iPadAppleMac OS XXCodeObjective-C
Hubs: Development for iOS
+5
1k 25
Comments 16