📜 ⬆️ ⬇️

Creating a scrollbar of pictures a la iPhoto. Part 1

Having started programming for the iPad, I did not find a component similar to the scroll bar in the iPhoto app for the iPad.
image
I tried to implement something like this.



First, create an ImageScrubberToolbar that we inherit from the 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 .
@ 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 .
@ 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 .


')
Now we will add the private methods ImageScrubberToolbar to the m-file.
@ interface ImageScrubberToolbar()
-( int ) checkTouchPosition:(CGPoint) aPoint;
-( void ) slideSelection:(CGPoint) aTouchPoint;
-( float ) leftMargin;
-( float ) rightMargin;
@end


* This source code was highlighted with Source Code Highlighter .
@ interface ImageScrubberToolbar()
-( int ) checkTouchPosition:(CGPoint) aPoint;
-( void ) slideSelection:(CGPoint) aTouchPoint;
-( float ) leftMargin;
-( float ) rightMargin;
@end


* This source code was highlighted with Source Code Highlighter .
@ interface ImageScrubberToolbar()
-( int ) checkTouchPosition:(CGPoint) aPoint;
-( void ) slideSelection:(CGPoint) aTouchPoint;
-( float ) leftMargin;
-( float ) rightMargin;
@end


* This source code was highlighted with Source Code Highlighter .



We describe the delegate protocol for reacting to the image selection event.
@protocol ImageScrubberToolbarDelegate
-( void )imageSelected:( int ) anIndex;
@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 .
@protocol ImageScrubberToolbarDelegate
-( void )imageSelected:( int ) anIndex;
@end


* This source code was highlighted with Source Code Highlighter .



In the method – (id)initWithCoder:(NSCoder *)aDecoder we will add custom initialization.
// 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 .
// 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 .
// 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 .



Now we are implementing the method -(void) setImagesArray:(NSArray *) array for specifying an array of displayed images.
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 .
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 .
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 .



The next step is the implementation of methods for checking the touch point and shift of the selection window.
-( 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 .
-( 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 .
-( 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 .



To handle touch events, add the following code.
-( 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 .
-( 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 .
-( 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 .



The next steps are to add ImageScrubberToolbarDelegate to the protocols implemented by our Application Delegate, add an ImageScrubberToolbar outlet to the Application Delegate members and implement the method -(void)imageSelected:(int) anIndex .
So, we have implemented all the main classes and methods.

Our ImageScrubberToolbar will look like this -
image

You can download the source code of the ImageScrubber project.
Continue here.

Source: https://habr.com/ru/post/90488/


All Articles