How to animate the movement of a UILabel - iphone

I am moving a UILabel around in my app and I would like it to change location and size over a few frames instead of jumping location. I am using Objective-c and cocoa developing for the Iphone. Can anyone help me out?

The easiest way to do it is like:
CGRect endFrame = /*The frame of your label in end position*/
[UIView animateWithDuration:0.5 animations:^{
myLabel.frame = endFrame;
}];

This Code is Helpful for your problem
#define FONT_SIZE 14
#define DURATION 10
#define DELAY 10
-(void)viewWillAppear:(BOOL)animated {
NSString* string = #"My Label";
CGSize framesize = [string sizeWithFont:[UIFont fontWithName:#"Copperplate" size:FONT_SIZE]];
// Origin
float x0 = 0;
float y0 = 0;
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
CGFloat appFrameWidth = appFrame.size.width;
CGFloat appFrameHeight = appFrame.size.height;
// Destination
float x1 = appFrameWidth - framesize.width;
float y1 = appFrameHeight - framesize.height;
UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(x0, y0, framesize.width, framesize.height)];
label.backgroundColor = [UIColor clearColor];
label.text = string;
label.shadowColor = [UIColor grayColor];
label.shadowOffset = CGSizeMake(1,2);
label.font = [UIFont fontWithName:#"Copperplate" size:FONT_SIZE];
[self.view addSubview:label];
[UIView animateWithDuration:DURATION
delay:DELAY
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
label.frame = CGRectMake(x1, y1, framesize.width, framesize.height);
}
completion:^(BOOL finished){
[label removeFromSuperview];
}];
}

Related

Image rotate and scale

I need to rotate and scale a UIImageView image with the help of UISlider.
There are three condition when UISlider value is in its middle position then the original image will be its original position.
Second case, When slider value is maximum then image will rotate with 45 degree add bit scale.
Third case, when slider value is in its minimum position then image will rotate 45 degree in opposite direction and also bit scale.
I used this code but did not get desired result.
-(IBAction)sliderMoved:(id)sender
{
UIImage *image = [UIImage imageNamed:#"landscape.jpg"];
photoImage.transform = CGAffineTransformMakeRotation(slider.value * 2*M_PI_2 / slider.maximumValue);
CGFloat scale=0.5;
NSLog(#"sliderVlaue=%f",slider.value);
if ((slider.value) >(0.75)) {
scale =(.25+ slider.value);
} else {
scale =(0.75 +slider.value);
}
CGAffineTransform currentTransform = photoImage.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[photoImage setTransform:newTransform];
}
you can try this code
CGFloat Angle=(((int)slider.value*M_PI)/180);
transform=CGAffineTransformScale(transform, photoImage.scale, photoImage.scale);
transform= CGAffineTransformRotate(transform,Angle);
photoImage.transform = transform;
You can use this code for image rotation
imageview.transform = CGAffineTransformMakeRotation(M_PI);
For scaling an image
-(IBAction)grow
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:YES];
CGRect b = grower.bounds;
b.size.height = 200;
b.size.width = 200;
grower.bounds = b;
[UIView commitAnimations];
}
I tried my self with the help of given hints and able to way out from my problem. here is the code`
in you h file declare UIImageView *photoImage;
UIView *canvas;
CAShapeLayer *_marque;
And in view did load
if (!_marque) {
_marque = [CAShapeLayer layer] ;
_marque.fillColor = [[UIColor clearColor] CGColor];
_marque.strokeColor = [[UIColor grayColor] CGColor];
_marque.lineWidth = 1.0f;
_marque.lineJoin = kCALineJoinRound;
_marque.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:10],[NSNumber numberWithInt:5], nil];
_marque.bounds = CGRectMake(photoImage.frame.origin.x, photoImage.frame.origin.y, 0, 0);
_marque.position = CGPointMake(photoImage.frame.origin.x + canvas.frame.origin.x, photoImage.frame.origin.y + canvas.frame.origin.y);
}
[[self.view layer] addSublayer:_marque];
- (IBAction) sliderMoved:(id)sender
{
CGFloat scale=0;
NSLog(#"sliderVlaue=%f",slider.value);
if ((slider.value) >(0.77)) {
scale =(.5+ slider.value);
photoImage.transform = CGAffineTransformMakeRotation(((4*slider.value)*(M_PI/180)));
CGAffineTransform currentTransform = photoImage.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale-.25, scale-.25);
[photoImage setTransform:newTransform];
NSLog(#"max=%f",scale);
}else if(slider.value< 0.77 && slider.value >.73){
photoImage.transform=CGAffineTransformIdentity;
photoImage.frame=imageframe;
scale =(0.5 +slider.value);
NSLog(#"mid=%f",scale);
}
else{
scale =(.77 +(1.0-slider.value));
photoImage.transform = CGAffineTransformMakeRotation((((-4)*(slider.value))*(M_PI/180)));
CGAffineTransform currentTransform = photoImage.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[photoImage setTransform:newTransform];
NSLog(#"min=%f",scale);
}
//_lastScale = 1;
[self showOverlayWithFrame:photoImage.frame];
}
-(void)showOverlayWithFrame:(CGRect)frame {
if (![_marque actionForKey:#"linePhase"]) {
CABasicAnimation *dashAnimation;
dashAnimation = [CABasicAnimation animationWithKeyPath:#"lineDashPhase"];
[dashAnimation setFromValue:[NSNumber numberWithFloat:0.0f]];
[dashAnimation setToValue:[NSNumber numberWithFloat:15.0f]];
[dashAnimation setDuration:0.5f];
[dashAnimation setRepeatCount:HUGE_VALF];
[_marque addAnimation:dashAnimation forKey:#"linePhase"];
}
_marque.bounds = CGRectMake(frame.origin.x, frame.origin.y, 0, 0);
_marque.position = CGPointMake(frame.origin.x + canvas.frame.origin.x, frame.origin.y + canvas.frame.origin.y);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, frame);
[_marque setPath:path];
CGPathRelease(path);
_marque.hidden = NO;
}
You can do it with the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
imgToRotate = [[UIImageView alloc]initWithFrame:CGRectMake(48, 208, 240, 240)];
imgToRotate.image = [UIImage imageNamed:#"rtm.jpeg"];
[self.view addSubview:imgToRotate];
}
- (IBAction)slideToRotateScale:(UISlider *)sender
{
sender.maximumValue = 1.0;
sender.minimumValue = -1.0;
imgToRotate.transform = CGAffineTransformRotate(CGAffineTransformMakeScale(fabsf(sender.value), fabs(sender.value)), sender.value*M_PI/4);
}

UIAccessibility VoiceOver announces wrong page number for UIScrollView

I am trying to make an existing app as accessible as possible for voice over.
Currently, I have a uiviewcontroller thats basically a paging photo view with a uipagecontrol below the uiscrollView (tourScrollView) that indicates the current image/page being viewed.
here's the code that calculate's the current page:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
CGFloat pageWidth = scrollView.frame.size.width;
self.tourScrollView.isAccessibilityElement = NO;
scrollView.isAccessibilityElement = NO;
int currentPage = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = currentPage;
}
the page calculation code works perfect.
There are a total of 5 images being shown.
With voice over enabled, when the scroll view scrolls, instead of going
page 1 of 5
page 2 of 5
page 3 of 5
page 4 of 5
page 5 of 5
it goes like this.
page 1 of 6
page 2 of 6
page 3 of 6
page 5 of 6
page 6 of 6
Here's the code where the images are added to the scrollView
-(void)addImagesToScrollview{
NSArray *welcomeImages = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"img-01.png"],
[UIImage imageNamed:#"img-02.png"],
[UIImage imageNamed:#"img-03.png"],
[UIImage imageNamed:#"img-04.png"],
[UIImage imageNamed:#"img-05.png"],nil];
CGRect scrollViewFrame = tourScrollView.frame;
CGFloat scrollViewWidth = scrollViewFrame.size.width;
CGFloat scrollViewHeight = scrollViewFrame.size.height;
CGFloat imageX;
for (int i = 0; i<[welcomeImages count]; i++) {
int index = i;
imageX = (scrollViewWidth*index) + (scrollViewWidth - IMAGE_WIDTH)/2.0;
CGRect boarderViewRect = CGRectMake(imageX, 20.0f, IMAGE_WIDTH, IMAGE_HEIGHT);
UIView *whiteBorderView = [[UIView alloc] initWithFrame:boarderViewRect];
whiteBorderView.backgroundColor = [UIColor whiteColor];
UIImageView *imageView = [[UIImageView alloc]initWithImage:[welcomeImages objectAtIndex:i]];
CGRect imageRect = CGRectInset(boarderViewRect, IMAGE_INSET, IMAGE_INSET);
imageView.frame = imageRect;
CGRect descriptionRect = CGRectMake((scrollViewWidth*index) + 20.0f, imageRect.origin.y + imageRect.size.height+10, 280, 90);
CGSize maximumLabelSize = CGSizeMake(descriptionRect.size.width,120);
descriptionRect.size = [[self descriptionForIndex:i] sizeWithFont:[UIFont systemFontOfSize:16.0] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeTailTruncation];
UILabel *imageDescription = [[UILabel alloc] initWithFrame:descriptionRect];
imageDescription.text = [NSString stringWithFormat:#"%#",[self descriptionForIndex:i]];
imageDescription.numberOfLines = 0;
imageDescription.backgroundColor = [UIColor clearColor];
imageDescription.font = [UIFont systemFontOfSize:16.0];
imageDescription.textColor = [UIColor colorWithRed:(119.0/255.0) green:(119.0/255.0) blue:(119.0/255.0) alpha:1.0];
imageDescription.textAlignment = UITextAlignmentCenter;
imageDescription.shadowColor = [UIColor whiteColor];
imageDescription.shadowOffset = CGSizeMake(0,1);
[tourScrollView addSubview:whiteBorderView];
[tourScrollView addSubview:imageView];
[tourScrollView addSubview:imageDescription];
if (i == [welcomeImages count]-1) {
tourScrollView.contentSize = CGSizeMake(imageView.frame.origin.x + scrollViewWidth -((scrollViewWidth - IMAGE_WIDTH)/2.0), scrollViewHeight);
}
}
}
I'd appreciate if someone points me to the right direction to make voice over say the correct page numbers.
update: Enabling/disabling pagingEnabled makes no difference. I think voiceOver overrides the paging calculations I do based on the scrollview size.
Here's what fixed it:
removed the commented code, and added a line for the content size outside the for loop
-(void)addImagesToScrollview{
NSArray *welcomeImages = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"img-01-welcome.png"],
[UIImage imageNamed:#"img-02-welcome.png"],
[UIImage imageNamed:#"img-03-welcome.png"],
[UIImage imageNamed:#"img-04-welcome.png"],
[UIImage imageNamed:#"img-05-welcome.png"],nil];
CGRect scrollViewFrame = tourScrollView.frame;
CGFloat scrollViewWidth = scrollViewFrame.size.width;
CGFloat scrollViewHeight = scrollViewFrame.size.height;
CGFloat imageX;
for (int i = 0; i<[welcomeImages count]; i++) {
int index = i;
imageX = (scrollViewWidth*index) + (scrollViewWidth - IMAGE_WIDTH)/2.0;
CGRect boarderViewRect = CGRectMake(imageX, 20.0f, IMAGE_WIDTH, IMAGE_HEIGHT);
UIView *whiteBorderView = [[UIView alloc] initWithFrame:boarderViewRect];
whiteBorderView.backgroundColor = [UIColor whiteColor];
UIImageView *imageView = [[UIImageView alloc]initWithImage:[welcomeImages objectAtIndex:i]];
CGRect imageRect = CGRectInset(boarderViewRect, IMAGE_INSET, IMAGE_INSET);
imageView.frame = imageRect;
CGRect descriptionRect = CGRectMake((scrollViewWidth*index) + 20.0f, imageRect.origin.y + imageRect.size.height+10, 280, 90);
CGSize maximumLabelSize = CGSizeMake(descriptionRect.size.width,120);
descriptionRect.size = [[self descriptionForIndex:i] sizeWithFont:[UIFont systemFontOfSize:16.0] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeTailTruncation];
UILabel *imageDescription = [[UILabel alloc] initWithFrame:descriptionRect];
imageDescription.text = [NSString stringWithFormat:#"%#",[self descriptionForIndex:i]];
imageDescription.numberOfLines = 0;
imageDescription.backgroundColor = [UIColor clearColor];
imageDescription.font = [UIFont systemFontOfSize:16.0];
imageDescription.textColor = [UIColor colorWithRed:(119.0/255.0) green:(119.0/255.0) blue:(119.0/255.0) alpha:1.0];
imageDescription.textAlignment = UITextAlignmentCenter;
imageDescription.shadowColor = [UIColor whiteColor];
imageDescription.shadowOffset = CGSizeMake(0,1);
[tourScrollView addSubview:whiteBorderView];
[tourScrollView addSubview:imageView];
[tourScrollView addSubview:imageDescription];
// if (i == [welcomeImages count]-1) {
// tourScrollView.contentSize = CGSizeMake(imageView.frame.origin.x + scrollViewWidth -((scrollViewWidth - IMAGE_WIDTH)/2.0), scrollViewHeight);
// }
}
tourScrollView.contentSize = CGSizeMake(320.0*[welcomeImages count], scrollViewHeight);
}
I am still not sure why VO would mess up the page numbers. The scrollview behavior, before and after the fix is still the same (bouncing and paging work identical).
will update the answer if I get to know more about this issue.
One easy option is to conform to your UIScrollViewDelegate to UIScrollViewAccessibilityDelegate and return the desired string.
For example:
extension MyScrollViewDelegate: UIScrollViewAccessibilityDelegate {
func accessibilityScrollStatus(for scrollView: UIScrollView) -> String? {
"\(self.currentPage) of \(self.pageCount)"
}
}

sizeWithFont:constrainedToSize:lineBreakMode: not accurate?

sizeWithFont:constrainedToSize:lineBreakMode: don't seem to be returning me the correct width. After these codes are executed, I see that part of the string in the label is chopping off, which means I've to manually add a few pixels to the size. Am I missing something?
I've a UILabel:
theLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, LABELWIDTH, LABELHEIGHT)];
theLabel.lineBreakMode = UILineBreakModeWordWrap;
theLabel.numberOfLines = 0;
[theLabel setFont:[UIFont fontWithName:#"MarkerFelt-Wide" size:16]];
theLabel.textColor = [UIColor blackColor];
theLabel.textAlignment = UITextAlignmentLeft;
theLabel.backgroundColor = [UIColor clearColor];
I tried to programmatically modify the size of the label using the following:
CGSize maximumLabelSize = CGSizeMake(LABELWIDTH, 10000);
CGSize expectedLabelSize = [someString sizeWithFont:theLabel.font constrainedToSize:maximumLabelSize lineBreakMode:theLabel.lineBreakMode];
theLabel.text = someString;
CGRect newFrame = theLabel.frame;
newFrame.size.height = expectedLabelSize.height;
newFrame.size.width = newFrame.size.width+50;
theLabel.frame = newFrame;
Ok, well, the first thing I'll say is that there are some very useful ways to deal with frames that you currently aren't employing. For example, your code,
CGRect newFrame = theLabel.frame;
newFrame.size.height = expectedLabelSize.height;
newFrame.size.width = newFrame.size.width+50;
theLabel.frame = newFrame;
Can be rewritten with functions from CGGeometry,
CGFloat widthOffset = 50.0f;
theLabel.frame = CGRectOffset(CGRectInset(theLabel.frame, widthOffset, 0.0f), widthOffset / 2.0f, 0.0f);
However, if your code worked as it was intended, you would not need to do this at all. You can go two routes,
[theLabel sizeToFit];
Or, this should also work,
theLabel.frame = CGRectMake(theLabel.frame.origin.x, theLabel.frame.origin.y, expectedLabelSize.width, expectedLabelSize.height);
No where in your earlier code did you change the width of theLabel to match the expected width. Notice, you wrote newFrame.size.width = newFrame.size.width+50 and that should be newFrame.size.width = expectedLabelSize.width.

how to animate the uilabel view in such a way that it should keep moving from right side of the screen towards left , in obj c

how to animate the uilabel view in such a way that it should keep moving from right side of the screen towards left ,
i have used the folloiwing code but it didnt work
UILabel * lbl =[UILabel alloc]init];
CALayer *cloud = [CALayer layer];
cloud.contents = lbl.text;
cloud.bounds = CGRectMake(0, 40, 100, 30);
cloud.position = CGPointMake(-45 ,30);
//cloud.position = CGPointMake(self.view.bounds.size.width / 2,cloudImage.size.height / 2);
[self.view.layer addSublayer:cloud];
CGPoint startPt = CGPointMake(self.view.bounds.size.width + cloud.bounds.size.width / 2,
cloud.position.y);
CGPoint endPt = CGPointMake(cloud.bounds.size.width / -2,
cloud.position.y);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim.fromValue = [NSValue valueWithCGPoint:startPt];
anim.toValue = [NSValue valueWithCGPoint:endPt];
anim.repeatCount = 1;
anim.duration = 5.0;
[cloud addAnimation:anim forKey:#"position"];
It's a lot easier if you can use animateWithDuration in ios4
UILabel *label = //new label
[UIView animateWithDuration:1.0 animations:^{
label.frame = //new frame
}];
You can do it like this:
UILabel *label = [[UILabel alloc] initWithFrame:theRect];
[self.view addSubview:label];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseIn
animations:^{label.bounds = targetRect;}
completion:^(BOOL finished) { /* completion stuff */}];
There are more animate methods that take less parameters. You find them in the UIView documentation.

I want to place imageview at different position with animation

I am trying to set multiple image on different position this is my code anyone help me to set imageview on different position.
- (void)viewDidLoad
{
[super viewDidLoad];
frameX = 45.0f;
frameY = 60.0f;
imagearr = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"King2.png"],
[UIImage imageNamed:#"3.png"],[UIImage imageNamed:#"queen.png"],
[UIImage imageNamed:#"King.png"],nil];
}
-(IBAction)hidebtn:(id)sender
{
[btn setHidden:TRUE];
[self setCards];
}
-(void)setCards
{
CGFloat dx = self.view.frame.size.width/2;
CGFloat dy = self.view.frame.size.height/2;
[cards setAnimationImages:imagearr];
CGRect frame = cards.frame;
frame.size.width = frameX;
frame.size.height = frameY;
[cards setFrame:frame];
cards.animationRepeatCount = 1;
for (int i=0; i<5;i++)
{
[UIView beginAnimations:#"Move" context:nil];
[UIView setAnimationDuration:0.3];
switch (i)
{
- (void)viewDidLoad
{
[super viewDidLoad];
frameX = 45.0f;
frameY = 60.0f;
imagearr = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"King2.png"],
[UIImage imageNamed:#"3.png"],[UIImage imageNamed:#"queen.png"],
[UIImage imageNamed:#"King.png"],nil];
}
-(IBAction)hidebtn:(id)sender
{
[btn setHidden:TRUE];
[self setCards];
}
-(void)setCards
{
CGFloat dx = self.view.frame.size.width/2;
CGFloat dy = self.view.frame.size.height/2;
[cards setAnimationImages:imagearr];
CGRect frame = cards.frame;
frame.size.width = frameX;
frame.size.height = frameY;
[cards setFrame:frame];
cards.animationRepeatCount = 1;
for (int i=0; i<5;i++)
{
[UIView beginAnimations:#"Move" context:nil];
[UIView setAnimationDuration:0.3];
switch (i)
{
case 0:
[cards setCenter:CGPointMake(dx, dy-120.0)];
cards.transform = CGAffineTransformMakeRotation(0);
break;
default:
break;
}
[self.view addSubview:cards];
[UIView commitAnimations];
}
default:
break;
}
[self.view addSubview:cards];
[UIView commitAnimations];
}
You are adding subviews too late, you can't animate what is not on screen. Add them before you start animations on some position then animate to the target position.