UIImageView's start animation does not animate flipped images - ios

I have a set of images facing one side(Man facing right side), and I'm flipping it using this method and then adding it into a uiimageview's animationImages. However after adding in the flipped images, and then start to animate, the animation is still facing the right side.
manRunAnimations = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 64, 64)];
NSArray *manAniRunArray = #[[UIImage imageNamed:#"robot1"],
[UIImage imageNamed:#"robot2"],
[UIImage imageNamed:#"robot3"],
[UIImage imageNamed:#"robot4"],
[UIImage imageNamed:#"robot5"],
[UIImage imageNamed:#"robot6"],
];
manRunAnimationsf = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 64, 64)];
NSMutableArray *flippedRunAnimationImages = [[NSMutableArray alloc] init];
for( UIImage *image in manAniRunArray)
{
UIImage * flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationRightMirrored];
[flippedRunAnimationImages addObject:flippedImage];
}
manRunAnimationsf.animationImages = (NSArray *)flippedRunAnimationImages;
testImgView.image = [manRunAnimationsf.animationImages objectAtIndex:0];
manRunAnimationsf.animationDuration = runAnimationSpeedSlider.value;
[manRunAnimationsf startAnimating];
I've even tested it using
testImgView.image = [manRunAnimationsf.animationImages objectAtIndex:5];
This would display one of the flipped images properly on screen just before I do a
[manRunAnimationsf startAnimating];
Once it starts, the animations are not flipped at all!!
Anyone know why?

I can't believe no one knows why, but I found way around it. Is to add the following before I startAnimating:
manRunAnimationsf.transform = CGAffineTransformMake(-1,0,0,1,0,0);
I didn't even need to do the CGImage flips in that for loop.
But the manual image flip should have worked with the imageWithCGImage method, and I really want to know why!! You guys disappoint me. :p

Related

NSMutableArray creates issue for images

I have an array with dictionaries in it. Each dictionary contains UIImage & String values.
But when I try to delete object using
[arr removeObjectAtIndex:button.tag];
then it just decreases the count but image (Object) is not deleted.
So, my Images are overlapping when try to delete.
It also creates problem when I try to add objects in the array
[arr insertObject:dict atIndex:0];
so, I used
[_postObj.arr_images addObject:dict]; instead of insertObject
Help me to solve this
Objects use reference counting and both NSMutableArray and UIImageView will retain the UIImage object.
This means that removing it from the array will not automatically remove it from the UIImageView and you must remove it from both explicitly:
[arr removeObjectAtIndex:button.tag];
_imageView.image = nil;
Problem is in your frame setting of UIImageView. Please try using below code (not tested by myself) and see if this fixes the issue for you. Basically, I am adjusting X position of images based on previous image's width.
CGFloat imageXM = 5.0;
CGFloat imageXPos = 0;
for (UIImage *image in arr_images) {
CGRect imageFrame = CGRectMake(imageXPos + imageXM, 0.0, image.size.width, image.size.height);
imageXPos = imageXPos + image.size.width;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = image;
[scl addSubview:imageView];
}
As in your code
[picker dismissViewControllerAnimated:YES completion:^{
[arr_images insertObject:chosenImage atIndex:0];
[self scrollImages_Setup2];
}];
[arr_images insertObject:chosenImage atIndex:0]; that means you need only one image to display on scroll view. Then why you take a loop:
-(void)scrollImages_Setup2
{
for (int k=0; k<arr_images.count; k++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((CGRectGetWidth(scl.frame) * k) + CGRectGetWidth(scl.frame), 0, CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame))];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image=[arr_images objectAtIndex:k] ;
[scl addSubview:imageView];
}
scl.contentSize = CGSizeMake((CGRectGetWidth(scl.frame) * arr_images.count)+CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame));
}
You just right the code only for display the Image. you don't need to scroll view for displaying only one image. I think you are not clear what you want.
Your problem regarding the overwriting the images because of loop. so remove the loop, when you display a single image. Please remove the scrollview contentSize, because image_array will increase, when you add the multiple images in array and size width will be large. so remove arr_images.count as well.

Using a String as Images Name

I am working on a while loop that spits out 30 images, each image having a different name. The way I approached this was by creating a NSString variable call img, which will be different with each iteration, i.e., "Badguy 1", "Badguy 2", ect... Then using that string as the name of the image being created.
TotalShips = 1
while(TotalShips < 31){
img = [NSString stringWithFormat:#"Badguy %i",TotalShips];
UIImageView *img = [[UIImageView alloc] initWithFrame: CGRectMake(10,20,20,20)];
img.image = [UIImage imageNamed:#"Badguy.png"];
[self.view addSubview: img];
TotalShips = TotalShips + 1;
}
This doesn't seem to work, and I haven't found very much help on changing an image's name.
Thanks,
Alex
The UIImageView has an property animatedImages (NSArray). Vou can easily play auround with animationDuration and animationReapCount. You can start the animation with [myImageView startAnimation] and stop with [myImageView stopAnimation].
Please read: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImageView_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006889-CH3-SW3
The file names can you build in a loop with 'NSString *fileName = [NSString stringWithFormat:#"image%i.png",imageName, iterator]'.
Not sure what you're trying to do, but I'll try to explain what your code does, maybe it helps you understand the problem:
TotalShips = 1
while(TotalShips < 31){
// here your img variable is a string, which will be 'Badguy 1', 'Badguy 2', etc
// you're not using this img value set here anywhere else in your code
img = [NSString stringWithFormat:#"Badguy %i",TotalShips];
// here you redeclare your img as an UIImageView
UIImageView *img = [[UIImageView alloc] initWithFrame: CGRectMake(10,20,20,20)];
// here you assign the image in the imageView to the image 'Badguy.png'
img.image = [UIImage imageNamed:#"Badguy.png"];
[self.view addSubview: img];
TotalShips = TotalShips + 1;
}
So, your code creates 30 different UIImageViews , all of them with the same image: 'Badguy.png', and adds them one on top of the other to the current view. I suppose this is not what you wanted to do.

iOS: ImageView filled with a picture

I have a table that contains the path to the picture, saved on user's library. Then, I pass this path to a View that contains just a imageView. I want to fills this ImageView with the picture. Like WhatsApp (when you click on a profile's picture). But, my picture it's always cropped or distorted. I tryed different ways to do this, but I didn't find the best way:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.translucent = NO;
UIImage *picture = [UIImage imageWithContentsOfFile: self.picturePath]; //I passed this path from the previous View
UIImageView* imageView = [[UIImageView alloc] initWithImage:picture];
CGRect screenRect = [[UIScreen mainScreen] bounds];
imageView.frame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);
imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.view addSubview:imageView];
}
Original (I want something like it)
My app
If your image is cut , the reason is you are using a higher resolution image in a smaller container and instructed your imageview to fill , using this line imageView.contentMode = UIViewContentModeScaleAspectFill;
Change it to imageView.contentMode = UIViewContentModeScaleAspectFit;
I think #whitewolf09 is right and his method will solve your problem. But i suggest you to look into MGImageUtilities that will be very useful for different cases where you can crop images maintaining aspect ratio to fit inside your image view's frame.
Just #import "UIImage+ProportionalFill.h"
UIImage *image = [[UIImage imageWithContentsOfFile:filePath] imageScaledToFitSize:imageView.frame.size];
That's the very useful category for image resizing and may help you in future.
I think the reason it is being clipped is that you are creating the image view with a picture THEN setting the frame and probably the picture is bigger than the frame so it is clipping it. Also try changing the aspect to: 'UIViewContentModeScaleAspectFit' Try this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.translucent = NO;
UIImage *picture = [UIImage imageWithContentsOfFile:self.picturePath]; //I passed this path from the previous View
UIImageView* imageView = [[UIImageView alloc] initWithRect:CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);];
CGRect screenRect = [[UIScreen mainScreen] bounds];
imageView.image = picture;
imageView.contentMode = UIViewContentModeCenter;
[self.view addSubview:imageView];
}

Trouble with animation on UIImageView

I have 7 images which i'm trying to make fade in/out of 1 ImageView. I have stored all the images in an array, and then have a loop to display each image and fade into the next, however, when i run the program only the last 2 images show up. Any ideas on why this is? and how to fix it? Code is below.
imageArray = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image 0.jpg"],
[UIImage imageNamed:#"image 1.jpg"],
[UIImage imageNamed:#"image 2.jpg"],
[UIImage imageNamed:#"image 3.jpg"],
[UIImage imageNamed:#"image 4.jpg"],
[UIImage imageNamed:#"image 5.jpg"],
[UIImage imageNamed:#"image 6.jpg"],
nil];
self.imageview.backgroundColor = [UIColor blackColor];
self.imageview.clipsToBounds = YES;
int count = [imageArray count];
for (int i = 0; i <count-1 ; i++)
{
UIImage *currentImage = [imageArray objectAtIndex: i];
UIImage *nextImage = [imageArray objectAtIndex: i +1];
self.imageview.image = [imageArray objectAtIndex: i];
[self.view addSubview:self.imageview];
CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:#"contents"];
crossFade.duration = 5.0;
crossFade.fromValue = (__bridge id)(currentImage.CGImage);
crossFade.toValue = (__bridge id)(nextImage.CGImage);
[self.imageview.layer addAnimation:crossFade forKey:#"animateContents"];
self.imageview.image = nextImage;
};
Some things to note:
1) You are doing everything synchronously on a loop that has no delay between each transition, there's no point in animating a if on the next loop it will be replaced by the next and so on, until the last 2. Also, you are adding your imageView as a subview every time, also unnecessary.
2) You are changing the .image property of the imageView, and then changing the contents of the layer. Might as well use an UIView and have the same effect.
My recommendation is to make a method to swap from one image to the next, and have a NSTimer call the function every x amount of seconds until you passed through them all.
Edit: For the future:
self.imageview.backgroundColor = [UIColor blackColor];
self.imageview.clipsToBounds = YES;
are completely unnecessary :)
The .backgroundColor is drawn over by the UIImage you are displaying.
The .clipsToBounds is the default behavior of UIImageView (it shrinks/expands your image to it's size, but never draws outside)

Creating a custom progress bar with images

Pretty much what I am trying to do, is create the following image:
So this is a progress bar, which will show how many votes the client get in that option. How can I do that? I was wondering if I can use a mask (as I would in flex), but all the masking implementations that I found on the web are doing masks for UIImages, and not for UIImageView. I cannot do the mask in the UIImage, because the two images have the same dimensions. I have to use the X and Y of the images to crop them?! So, any suggestions?
Here are the two images that I have to create that progress bar:
Cheers.
you want to get rid of all of the same bit in the middle of each image.
then do something like:
- (void)viewDidLoad
{
[super viewDidLoad];
[self addProgressBarInFrame:CGRectMake(20.f, 20.f, 280.f, 50.f) withProgress:.9f];
[self addProgressBarInFrame:CGRectMake(20.f, 100.f, 200.f, 25.f) withProgress:.1f];
}
-(void)addProgressBarInFrame:(CGRect)frame withProgress:(CGFloat)progress
{
float widthOfJaggedBit = 4.0f;
UIImage * imageA= [[UIImage imageNamed:#"imageA"] stretchableImageWithLeftCapWidth:widthOfJaggedBit topCapHeight:0.0f];
UIImage * imageB= [[UIImage imageNamed:#"imageB"] stretchableImageWithLeftCapWidth:widthOfJaggedBit topCapHeight:0.0f];
UIView * progressBar = [[UIView alloc] initWithFrame:frame];
progressBar.backgroundColor = [UIColor whiteColor];
UIImageView * imageViewA = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, frame.size.width*progress, frame.size.height)];
UIImageView * imageViewB = [[UIImageView alloc] initWithFrame:CGRectMake(frame.size.width*progress, 0.f, frame.size.width - (frame.size.width*progress), frame.size.height)];
imageViewA.image = imageA;
imageViewB.image = imageB;
// imageViewA.contentStretch = CGRectMake(widthOfJaggedBit, 0, imageA.size.width - 2*widthOfJaggedBit, imageA.size.height) ;
// imageViewB.contentStretch = CGRectMake(widthOfJaggedBit, 0, imageB.size.width - 2*widthOfJaggedBit, imageB.size.height) ;
[self.view addSubview:progressBar];
[progressBar addSubview:imageViewA];
[progressBar addSubview:imageViewB];
}
Grady Player's answer is great. Just a small note, for anyone that uses this. I tried to update the frames of the two UIImageView's to update the "progress". I tried to force an update with "setNeedsDisplay", but to no avail. (sizeToFit caused problems too).
Anyway, the only way I figured out how to update the progress of an existing progress bar was to call "setFrame:CGRectMake" with my new dimensions.

Resources