I parse an XML in my blog app. When I parse it, I have created an object called entry, with properties for Title, Article, Link, Content, and Image. I then have a mutable array called entries that after parsing is finished, I add to entries the object entry. This way, to get the Title of a certain article in a tableview, I can call
RSSEntry *entry = [_Entries objectAtIndex:indexPath.row];
NSString *title = entry.Title;
What I would like to do is have a UIImageView above the tableview, and set that to scroll through all the different UIImages in the array, but am unsure of how to accomplish this. I know of the animationImages property, but not sure what to set as the NSArray in all this, since I use Mutable Array with properties. Any suggestions would greatly help.
There are two options:
a) collect all the images in the separate array by iterating through _Entries to set the animationImages array value;
b) prepare your own view, initialize the timer at constructor with [NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:], change the displayed image at selector. To make a smooth animation you can use two imageView subviews setting animated the displayed imageView alpha from 1 to 0 and the next imageView alpha from 0 to 1. As the datasource you can use array of RSSEntry* taking the images from there with a known keypath.
The first option is fairly easier.
I hope you know how to put the UIImageView above the tableview in the xob/storyboard.
Than I am not sure what would you like to do with array of images, but if that mets your needs than it can be a swipe recognizer, and swipe the images
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UISwipeGestureRecognizer* recognizerLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeLeft)];
recognizerLeft.direction =UISwipeGestureRecognizerDirectionLeft;
recognizerLeft.numberOfTouchesRequired =1;
[self.view addGestureRecognizer:recognizerLeft];
[recognizerLeft release];
UISwipeGestureRecognizer* recognizerRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeRight)];
recognizerRight.direction =UISwipeGestureRecognizerDirectionRight;
recognizerRight.numberOfTouchesRequired =1;
[self.view addGestureRecognizer:recognizerRight];
[recognizerRight release];
}
- (IBAction)swipeLeft{
//NSLog(#"Swipe left");
if(pager.currentPage < pager.numberOfPages - 1){
pager.currentPage = (pager.currentPage + 1 );
[self pagerValueChanged];
}
}
- (IBAction)pagerValueChanged
{
NSData* imgData = [images objectAtIndex:pager.currentPage];
UIImage* img = [[UIImage alloc]initWithData:imgData];
imageView.image = img;
//NSLog(#"img width: %f, img height: %f", img.size.width, img.size.height);
[img release];
}
I have paging control and other controls too in my code, but you probably don't need those
This is pretty easy using array enumeration. The following code will take a scroll view that you have already configured and add image views to it for all the objects in your array. It will also dynamically adjust the content size of the scroll view based on the count of the array.
[myMutableArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[myMutableArray objectAtIndex:idx]]];
[myImageView setFrame:CGRectMake(myScrollView.frame.size.width * idx, myScrollView.frame.origin.y, myScrollView.frame.size.width, myScrollView.frame.size.height)];
[myScrollView addSubview:myImageView];
[myScrollView setContentSize:CGSizeMake((myScrollView.frame.size.width * idx) + myScrollView.frame.size.width, myScrollView.frame.size.height)];
}];
Related
In my app i have thumbnail view and i want the user to go to the next view with the imageview and show the particular thumbnail clicked.But this image view is attached to the UIScroll with paging and UIPagecontrol. So i want the specific image to be open and at the specific index so that the user can swipe left or right to see other images. This needs to be exactly like iPhoone's Photo app.
how can I solve this?
my code is,
collectionview.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *selectedIndexPath = [[self.gallerycollection indexPathsForSelectedItems] objectAtIndex:0];
// load the image, to prevent it from being cached we use 'initWithContentsOfFile'
NSString *imageNameToLoad = [NSString stringWithFormat:#"interior_%d", selectedIndexPath.row];
NSString *pathToImage = [[NSBundle mainBundle] pathForResource:imageNameToLoad ofType:#"jpg"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage];
GalleryImageScrollViewController *gallerydetailViewController = [segue destinationViewController];
gallerydetailViewController.FullScreenImageScroller=image ;
}
}
GalleryImageScrollViewcontroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *mutablearray = [NSMutableArray array];
data=[MyDatabase new];
slideImages=[data OpenMyDatabase:#"SELECT pic_name_big FROM interior":#"pic_name_big"];
[mutablearray addObjectsFromArray:slideImages];
temparr = [[NSMutableArray alloc]init];
temparr=[NSMutableArray arrayWithArray:mutablearray];
[self putImageViewsInScrollView:[temparr count]];
}
-(void) putImageViewsInScrollView:(int)numberOfImageViews
{
for(int i=0 ;i<= numberOfImageViews; i++)
{
// UIImageView *fullScreenImageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[temparr objectAtIndex:i]]];
fullScreenImageView.frame = CGRectMake((WIDTH_OF_IMAGE * i) , 0, WIDTH_OF_IMAGE, HEIGHT_OF_IMAGE);
[self.FullScreenImageScroller addSubview:fullScreenImageView];
}
[self.FullScreenImageScroller setContentSize:CGSizeMake(WIDTH_OF_SCROLL_PAGE * ([temparr count]), HEIGHT_OF_IMAGE)];
[self.FullScreenImageScroller setContentOffset:CGPointMake(0, 0)];
[self.FullScreenImageScroller scrollRectToVisible:CGRectMake(WIDTH_OF_IMAGE,0,WIDTH_OF_IMAGE,HEIGHT_OF_IMAGE) animated:NO];
self.FullScreenImageScroller.delegate=self;
}
This can help
KTPhotoBrowser
TTThumbs
You can use Three20 library or Apple's UICatalog sample for reference. Below are the links :
https://developer.apple.com/library/ios/#samplecode/UICatalog/Introduction/Intro.html
https://github.com/facebook/three20
you can map the index of the image in the array to the "tag" of the thumbnail view when first adding the images to the thumbnail
ThumbnailView *thumb = [UIView alloc] init];
thumb.image = [imagesArray objectAtIndex:i];
thumb.tag = i;
and when selecting the thumb view you can fetch the image from the array according to the tag
UIImage *image = [imagesArray objectAtIndex:thumb.tag];
try like this may be it works
1.for thumb nail image give image.tag value when you click on your thumb nail image pass that tag value to next view controller(detailviewControllerObj.index=image.tag) .
2.add all the full screen images (size 320*480) to scrollview in detail page and add that scrollview to view.
3.when you click on the thumb nail image you can pass the index value to detail screen.
4.after that set the scroll view content offset in detail screen.
[scroll setContentOffset:CGPointMake(320*index, 0)];
when ever you are creating thumb nail images at that time give like
for(int i=0;i<[imgarr count];i++)
{
UIImageView *imageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
imageView.image=[imgarr objectAtIndex:i];
imageView.tag=i;
[self.view addSubview:imageView];
}
after that in detail view take one integer value as index and synthesize that variable
when you click on that particular image give like this
detailviewControllerObj.index=image.tag
I can now display a UIImageView that is within an array but using the following:
[[self.guess objectAtIndex:1] setFrame:CGRectMake(20, 20, 100, 100)];
[self.view addSubview:[self.guess objectAtIndex:1]];
If I want to change the image within one of my UIImageViews within the array
I can use:
[self.guess replaceObjectAtIndex:1 withObject:Square];
but I then have to remove the original view, then add the new subview again:
[[self.guess objectAtIndex:1] removeFromSuperview];
[self.view addSubview:[self.guess objectAtIndex:1]];
The trouble is, my new subview does not inherit the frame position and size
of the original image (as this may have changed). Is there a way to do this
more easily?
I was hoping for something like this, that would just update the original
image in the same position, with the same size:
[self.guess.image replaceObjectAtIndex:1 withObject:Square.image];
Thanks again!
Would it be possible to store only the images in the array and just have one UIImageView? Then, just replace the image inside the UIImageView element
What Radu already said, its better to keep an array of images, or imageNames. Then you also do not have to remove the imageView from the superView, you just reuse the one and only one ImageView.
So what you left is something like this
yourImageView.image = [self.guess objectAtIndex:1];
And if you only store the names in the array
yourImageView.image = [UIImage imageNamed:[self.guess objectAtIndex:1]];
I don't if you've tried this yet, but this should work.
UIImageView *img = (UIImageView *)[self.guess objectAtIndex:1];
img.image = Your Image;
On iOS, if a view has several layers, then can the drawRect method just choose any one layer to display, and 1 second later, choose another layer to display, to achieve an animation effect?
Right now, I have several layers, but I don't think they are the view's layers (they are just individual layers which are not sublayers of parent layer), as I just created them using
CGLayerCreateWithContext(context, self.view.bounds.size, NULL);
and in drawRect, I use
CGContextDrawLayerAtPoint(context, self.bounds.origin, layer1);
to draw the layer onto the view... it works, but isn't this like drawing a layer onto a layer (drawing a layer onto the view's layer)? Isn't there a faster way, which is to tell the the view to use layer1 or layer2, kind of like
self.layer = layer1;
but it can't because layer is read only. Can this be achieved?
You are trying to draw CALayer objects using CGLayer drawing methods. These are different things, and will not work interchangeably. However, if I understood your question correctly, you don't need to use drawRect: at all to switch between layers after a period of time. Here is my basic working code example:
#import <QuartzCore/QuartzCore.h>
#interface TTView {
NSUInteger index;
NSArray *layers;
CALayer *currentLayer;
}
#end
#implementation TTView
- (void)switchView {
// Remove the currently visible layer
[currentLayer removeFromSuperlayer];
// Add in the next layer
currentLayer = [layers objectAtIndex:index];
[self.layer addSublayer:currentLayer];
// Increment the index for next time
index += 1;
if (index > [layers count] - 1) {
// If we have reached the end of the array, go back to the start. You can exit the loop here by calling a different method followed by return;
index = 0;
}
// Call this method again after 1 second
[self performSelector:#selector(switchView) withObject:nil afterDelay:1];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
// Basic initialisation. Move this to whatever method your view inits with.
self = [super initWithCoder:aDecoder];
if (self) {
// Create some random objects with layers to display. Place your layers into the array here.
UIView *a = [[UIView alloc] initWithFrame:self.bounds];
a.backgroundColor = [UIColor redColor];
UIView *b = [[UIView alloc] initWithFrame:self.bounds];
b.backgroundColor = [UIColor greenColor];
UIView *c = [[UIView alloc] initWithFrame:self.bounds];
c.backgroundColor = [UIColor blueColor];
// Add the layers to the array.
layers = [[NSArray alloc] initWithObjects:a.layer, b.layer, c.layer, nil];
// Call the method to start the loop.
[self switchView];
}
return self;
}
Obviously you should replace my 3 plain coloured views with whatever layers you are planning to animate in this way, and possibly tidy up the instance variables. This is simply a basic code example that does what you want.
Following #PartiallyFinite's example, here's a similar way to get the same sort of effect, by setting your view's layer's contents property to a CGImage of your choosing.
This is more efficient than overriding -drawRect: and drawing there, because it avoids an additional draw operation and upload to the video hardware.
#import <QuartzCore/QuartzCore.h>
#interface TTView {
NSUInteger index;
NSMutableArray *images;
}
#end
#implementation TTView
- (id)initWithCoder:(NSCoder *)aDecoder {
// Basic initialisation. Move this to whatever method your view inits with.
self = [super initWithCoder:aDecoder];
if (self) {
// Create some random images to display. Place your images into the array here.
CGSize imageSize = self.bounds.size;
images = [[NSMutableArray alloc] init];
[images addObject:[self imageWithSize:imageSize color:[UIColor redColor]]];
[images addObject:[self imageWithSize:imageSize color:[UIColor greenColor]]];
[images addObject:[self imageWithSize:imageSize color:[UIColor blueColor]]];
[self switchView];
}
return self;
}
- (UIImage*)imageWithSize:(CGSize)imageSize color:(UIColor*)color {
UIGraphicsBeginImageContext(imageSize);
// Draw whatever you like here.
// As an example, we just fill the whole image with the color.
[color set];
UIRectFill(CGRectMake(0, 0, imageSize.width, imageSize.height));
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void)switchView {
UIImage* image = [images objectAtIndex:index];
self.layer.contents = (id)(image.CGImage);
index = (index + 1) % images.count;
[self performSelector:#selector(switchView) withObject:nil afterDelay:1];
}
// DO NOT override -drawRect:, and DO NOT call -setNeedsDisplay.
// You're already providing the view's contents.
#end
i have my subviews stored in an array...what i want is to place these subviews to my main view from array....
for(int i=0;i<[imageViewArray count];i++)
{
NSLog(#" image array count is %d",[imageViewArray count]);
// countlayers= countlayers+1;
// [canvasView insertSubview:[imageViewArray objectAtIndex:i] atIndex:countlayers];
[canvasView addSubview:[imageViewArray objectAtIndex:i]];
}
can you tell me what i am doing wrong
If imageViewArray really contains initialized views, and if those views already have correct frame attributes, you're doing nothing wrong (even though your code could be more elegant).
Also, of course, we have to make sure that canvasView is indeed initialized and visible on the screen. Try setting its backgroundColor to something noticeable:
canvasView.backgroundColor = [UIColor greenColor];
Once you are sure the canvasView is actually being displayed, I would suggest using fast enumeration, which makes going through the array nicer, and logging your new subviews to make sure their frames are like you want them.
for (UIView *imageView in imageViewArray) //this is fast enumeration. You can get it through code completion by typing forin
{
NSLog(#"%#", imageView); //let's take a look at the imageView. What is its frame?
[canvasView addSubview:imageView];
}
Used enumeration to add images on your canvas View using imageViewArray and probably you are also missing with the setting frame of the images.
for (UIImageView *imageView in imageViewArray) //enumeration.
{
//let's set frame for image view before adding to canvasView
[imageView setFrame:CGRectMake(x,y,w,h)];
//Also make sure imageView has image or not
if(imageView.image)
[canvasView addSubview:imageView];
}
i have a UIButton in a viewcontroller's view, i wrote action method form that i am going to another view controller's view. Now i am trying to implement animation between to views.i tried with many types one of the type animation is shown below
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.view addSubview:anotherView];
[UIView commitAnimations];
This animation is working well but i am trying to implement some "growing flower animation"(name may be different) means the other view pop up from the button co-ordinatesand occupy entire screen.my custombutton` co-ordinates are (500,500,20,20).can any one suggest me for implementing this animation.
Thank you.
This can be achieved by various methods.
You can use:-
1 )
Core animations
UIImage class's animations
Cocos 2D
UIAnimation Classes (by simple changing the frames)
..and many more
It actually depends on your requirements, and your comfortable level with these classes/technologies.
If you just want to display growing flower, then the simpler (but not the optimized, and best) solution is to create different images,and put them in array, and then animate it
A similar example is available at: -
Animating images
If you have step by step images of growing flower images, then you can simply implement this. Write a function to implement simple implementation,
NSMutableArray * images;
//allocates the images array.
images = [[NSMutableArray alloc] init];
//loops till the 18images are added into array.
for (int index = 1; index < 19; index++) {
//get the image name.
NSString * imageName = [NSString stringWithFormat:#"Animation%d",index];
//get the path for the image in resourse file.
NSString * path = [[NSBundle mainBundle] pathForResource:imageName ofType:#"png"];
//allocate and own the image object for the particular image.
UIImage *image = [[UIImage alloc] initWithContentsOfFile:path];
//adds it to array.
[images addObject:image];
//release after adding.
[image release];
//remove the useless pointer.
image = nil;
}
//give the pointer to the array holding the images.
imageView.animationImages = images;
//after using it, release it.
[images release];
//remove the useless pointer
images = nil;
//set animation duration
imageView.animationDuration = 3.00;
//start animate
[imageView startAnimating];
After when you want to stop the animation you can simply call
[imageView stopAnimation];
You have another choice of
imageView.repeatCount = 1;
imageView is an instance of uiimageView, allocated one.