Frame property of UIView is not getting assigned inside animation on iOS - ios

In my iOS app I'm trying to perform following simple animation:
- (void)dismissToolbar
{
NSLog(#"bx: %f by: %f bw: %f bh: %f ",
toolbar.frame.origin.x,
toolbar.frame.origin.y,
toolbar.frame.size.width,
toolbar.frame.size.height);
CGRect tempRect = CGRectMake(0,
toolbar.frame.origin.y + toolbar.frame.size.height,
toolbar.frame.size.width,
toolbar.frame.size.height);
[UIView animateWithDuration:animationsDuration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowAnimatedContent
animations:^{
NSLog(#"bx: %f by: %f bw: %f bh: %f ",
tempRect.origin.x,
tempRect.origin.y,
tempRect.size.width,
tempRect.size.height);
toolbar.frame = tempRect; // frame value doesn't change here!
}
completion:^(BOOL finished) {
NSLog(#"bx: %f by: %f bw: %f bh: %f ",
toolbar.frame.origin.x,
toolbar.frame.origin.y,
toolbar.frame.size.width,
toolbar.frame.size.height);
NSLog(#"dismiss toolbar complete");
[toolbar setHidden:YES];
isPlayerToolbarActive = NO;
isDissmissingToolbar = NO;
}
];
[[NSNotificationCenter defaultCenter] postNotificationName:#"animateSidePanels" object:#"removingPlayerToolbar"];
}
I'm getting the following output to a console from the logs above:
bx: 0.000000 by: 724.000000 bw: 1024.000000 bh: 44.000000
bx: 0.000000 by: 768.000000 bw: 1024.000000 bh: 44.000000
bx: 0.000000 by: 724.000000 bw: 1024.000000 bh: 44.000000
dismiss toolbar complete
as you can see the value of the frame didn't change...and I don't really understand why...
any kind of help is highly appreciated!

Did you create the view with xib's or interfaceBuilder?
If so, try selecting the xib and deselecting use autoLayout

Related

CGAffineTransformMakeTranslation does not translate correctly

I see two different behaviors for CGAffineTransformMakeTranslation between simulator mode and the real device.
(on iOS 8.1)
For an iPhone4, to get CGAffineTransformMakeTranslation to work on the real device, I have to translate by twice the amount.
On the iPhone4s simulator, I have to translate just by the amount with not scaling.
Perhaps I'm missing something obvious but since both have the same number of logical pixels, I shouldn't have to adjust CGAffineTransformMakeTranslation to make translation work.
Here I have a view I'm pulling in and out of view by swiping:
CGRect menuOrigin = self.rootController.containerView.bounds;
switch (direction) {
case UISwipeGestureRecognizerDirectionLeft:
{
NSLog(#"Initial Position: %#", NSStringFromCGPoint(self.rootController.containerView.frame.origin));
NSLog(#"Initial Scale: %f", [self contentScaleFactor]);
NSLog(#"Initial Center: %#", NSStringFromCGPoint([self center]));
CGAffineTransform transform = CGAffineTransformMakeTranslation(-1.0 * widthToSlide, 0);
self.rootController.containerView.transform = transform;
[UIView animateWithDuration:0.4 animations:^{
self.rootController.containerView.transform = transform;
[self.rootController.containerView layoutIfNeeded];
} completion:^(BOOL finished) {
NSLog(#"Final Position: %#", NSStringFromCGPoint(self.rootController.containerView.frame.origin));
NSLog(#"Final Scale: %f", [self contentScaleFactor]);
NSLog(#"Final Center: %#", NSStringFromCGPoint([self center]));
}];
}
break;
case UISwipeGestureRecognizerDirectionRight:
{
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, 0.0);
[UIView animateWithDuration:0.4 animations:^{
self.rootController.containerView.transform = transform;
[self.rootController.containerView layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
default:
break;
}
[self.rootController.containerView setNeedsDisplay];
[self setNeedsDisplay];
NSLog goes like this for the iPhone4 real device:
2015-10-15 01:12:37.547 Local[5307:60b] swipeLocalPull adjusting width 183
2015-10-15 01:12:37.556 Local[5307:60b] Screen size: {320, 480}
2015-10-15 01:12:37.559 Local[5307:60b] Initial Position: {0, 66}
2015-10-15 01:12:37.974 Local[5307:60b] Final Position: {-91.5, 66}
and for the iPhone4s iOS 8.1 simulator:
2015-10-15 01:19:19.479 Local[56380:3061577] swipeLocalPull adjusting width 183
2015-10-15 01:19:19.480 Local[56380:3061577] Screen size: {320, 480}
2015-10-15 01:19:19.480 Local[56380:3061577] Initial Position: {0, 66}
2015-10-15 01:19:19.886 Local[56380:3061577] Final Position: {-183, 66}
The simulator is translated correctly. Notice, the real device translated only half way to -91.5. Why is this and how can I detect or compensate for this. Sorry if this question has been asked before but I could not find the root cause for this behavior. I only care about x translation at this moment.
Anyone have clues for this behavior.?
Update
By request, here's a few extra outputs:
---iPhone4 values---
2015-10-15 17:20:59.591 Local[5617:60b] swipeLocalPull adjusting width 183
2015-10-15 17:20:59.596 Local[5617:60b] Screen size: {320, 480}
2015-10-15 17:20:59.599 Local[5617:60b] Initial Position: {0, 66}
2015-10-15 17:20:59.601 Local[5617:60b] Initial Scale: 2.000000
2015-10-15 17:20:59.603 Local[5617:60b] Initial Center: {201, 99}
2015-10-15 17:21:00.015 Local[5617:60b] Final Position: {-91.5, 66}
2015-10-15 17:21:00.018 Local[5617:60b] Final Scale: 2.000000
2015-10-15 17:21:00.037 Local[5617:60b] Final Center: {201, 99}
---iPhone4s Simulator---
2015-10-15 17:39:59.850 Local[57069:3104390] swipeLocalPull adjusting width 183
2015-10-15 17:39:59.851 Local[57069:3104390] Screen size: {320, 480}
2015-10-15 17:39:59.851 Local[57069:3104390] Initial Position: {0, 66}
2015-10-15 17:39:59.851 Local[57069:3104390] Initial Scale: 2.000000
2015-10-15 17:39:59.851 Local[57069:3104390] Initial Center: {201, 99}
2015-10-15 17:39:59.852 Local[57069:3104390] Final Position: {-183, 66}
2015-10-15 17:39:59.852 Local[57069:3104390] Final Scale: 2.000000
2015-10-15 17:39:59.852 Local[57069:3104390] Final Center: {201, 99}
They both seem to be at #2x scale so I expect the same code to work for both.
Working Code
I got it to work with the following(if someone explains why, then I'll just mark that as the answer):
switch (direction) {
case UISwipeGestureRecognizerDirectionLeft:
{
NSLog(#"Initial Position: %#", NSStringFromCGPoint(self.rootController.containerView.frame.origin));
NSLog(#"Initial Scale: %f", [self contentScaleFactor]);
NSLog(#"Initial Center: %#", NSStringFromCGPoint([self center]));
CGPoint currentPos = self.rootController.containerView.center;
currentPos.x -= widthToSlide;
[UIView animateWithDuration: .4
delay: 0
options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations:^{
self.rootController.containerView.center = currentPos;
}
completion:^(BOOL finished) { }
];
}
break;
case UISwipeGestureRecognizerDirectionRight:
{
CGPoint currentPos = self.rootController.containerView.center;
currentPos.x += widthToSlide;
[UIView animateWithDuration: .4
delay: 0
options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations:^{
self.rootController.containerView.center = currentPos;
}
completion:^(BOOL finished) { }
];
}
default:
break;
}
[self.rootController.containerView setNeedsDisplay];
[self setNeedsDisplay];

XCode In Call Status bar changing the view

I had created a Viewcontroller in XCode, everything is working fine. When a phone call comes, the in Call Status bar is pushing the button in the bottom of the view "DOWN" due to that I am unable to click the button during the phone call.
I would like to know how to keep the buttons in the bottom, the same position even when the phone call comes. I tried several methods nothing worked for me.
- (void)statusBarFrameWillChange:(NSNotification*)notification {
NSValue* rectValue = [[notification userInfo] valueForKey:UIApplicationStatusBarFrameUserInfoKey];
CGRect newFrame;
[rectValue getValue:&newFrame];
CGRect fixedFrame = bottomBar.frame;
fixedFrame.origin.y = fixedFrame.origin.y - newFrame.size.height; //Keep the Y position as it is
bottomBar.frame = fixedFrame;
NSLog(#"statusBarFrameWillChange: newSize %f, %f, %f", fixedFrame.origin.y, newFrame.size.width, newFrame.size.height);
}
- (void)statusBarFrameChanged:(NSNotification*)notification {
NSValue* rectValue = [[notification userInfo] valueForKey:UIApplicationStatusBarFrameUserInfoKey];
CGRect oldFrame;
[rectValue getValue:&oldFrame];
CGRect fixedFrame = bottomBar.frame;
fixedFrame.origin.y = fixedFrame.origin.y + oldFrame.size.height;
bottomBar.frame = fixedFrame;
NSLog(#"statusBarFrameChanged: oldSize %f, %f, %f", fixedFrame.origin.y, oldFrame.size.width, oldFrame.size.height);
}
Using autolayout, make sure you set a Bottom Space constraint:

UIView Animation Mac OSX Effect

I'm animating a small view with popup effect to alert you of an error ... The animation works perfectly but still are not very satisfied because I would like the view does not stop at position (x 25) but I wish they came to ( x 40 ) and then return immediately to ( x 25). In other words I would like to recreate the effect they have on the textfield MontainLion when you are wrong to insert the fields User for access to the operating system ...
I really hope to be able to explain to me , but if I did not succeed please comunicarmelo so that I can explain it better to resolve this question. Thanks to all! Rory .
Below I show you the code to display the pop-up I'm using
- (Void)presentazioneViewTransition
{
CGRect endREct ;
endREct = CGRectMake (25, 160, 270, 90);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.25];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(endRightAnimation)];
self.frame = endREct;
[UIView commitAnimations];
}
You can use the simple block based UIView animation methods like this
-(void)presentazioneViewTransition{
CGRect transitionRect = CGRectMake(40.0f, 160.0f, 270.0f, 90.0f);
CGRect endREct = CGRectMake (25.0f, 160.0f, 270.0f, 90.0f) ;
[UIView animateWithDuration:0.15f
animations:^{
self.frame = transitionRect;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.1f
animations:^{
self.frame = endREct;
}];
}];
}

Google Maps iOS SDK move "My Location" button to bottom left hand corner

Using the Google Maps for iOS SDK, the "My Location" button is by default placed in the bottom right hand corner:
I'd like to place it in the bottom left hand corner (yes, I realize I need to be careful not to obscure the "Google" logo there). I don't believe the SDK has an "official" way of doing this, but based on this answer I have figured out how to get a hold of the My Location button subview so that I can position it.
The part that has me confused is what values I should be giving to the My Location view's frame and/or bounds to get it where I want it. For starters, the My Location button as it currently stands has frame.origin.x = -74 and frame.origin.y = -54. This is the first time I've seen negative coordinates for a frame.origin.x or a frame.origin.y and I'm not even sure how iOS handles negative coordinates. My first thought was that e.g. frame.origin.x = -74 is equivalent to [view superview].frame.size.width - 74, i.e. negative value are subtracted from the width or height of the superview. But then I looked at the width and height of the superview and they're both 0.0. Here's my code which outputs some information about both the map and the my location button frames and bounds:
- (void)loadView {
GMSCameraPosition *cam = [GMSCameraPosition cameraWithLatitude:jcuTownsvilleCenterCampusLat longitude:jcuTownsvilleCenterCampusLon zoom:17];
self.campusMap = [GMSMapView mapWithFrame:CGRectZero camera:cam];
self.campusMap.myLocationEnabled = YES;
self.campusMap.settings.myLocationButton = YES;
self.view = self.campusMap;
for (UIView *view in self.campusMap.subviews) {
NSLog(#"view.description: %#",view.description);
if ([view isKindOfClass:[UIButton class]]) {
// these four values in the conditional below are just what happen to
// be the values corresponding to the "my location button" in Google Maps
// for iOS SDK version 1.3.0.3430. They might change over time, so this
// code is somewhat fragile.
if (view.frame.size.width == 76 && view.frame.size.height == 54 &&
view.frame.origin.x == -76 && view.frame.origin.y == -54) {
NSLog(#"we may have found the 'my location' button");
NSLog(#"self.campusMap coord stats:");
NSLog(#"bounds.origin.x: %f", self.campusMap.bounds.origin.x);
NSLog(#"bounds.origin.y: %f", self.campusMap.bounds.origin.y);
NSLog(#"bounds.size.width: %f", self.campusMap.bounds.size.width);
NSLog(#"bounds.size.height: %f", self.campusMap.bounds.size.height);
NSLog(#"frame.origin.x: %f", self.campusMap.frame.origin.x);
NSLog(#"frame.origin.y: %f", self.campusMap.frame.origin.y);
NSLog(#"frame.size.width: %f", self.campusMap.frame.size.width);
NSLog(#"frame.size.height: %f", self.campusMap.frame.size.height);
NSLog(#"view coord stats:");
NSLog(#"bounds.origin.x: %f", view.bounds.origin.x);
NSLog(#"bounds.origin.y: %f", view.bounds.origin.y);
NSLog(#"bounds.size.width: %f", view.bounds.size.width);
NSLog(#"bounds.size.height: %f", view.bounds.size.height);
NSLog(#"frame.origin.x: %f", view.frame.origin.x);
NSLog(#"frame.origin.y: %f", view.frame.origin.y);
NSLog(#"frame.size.width: %f", view.frame.size.width);
NSLog(#"frame.size.height: %f", view.frame.size.height);
}
}
}
}
And here is the output:
self.campusMap coord stats:
bounds.origin.x: 0.000000
bounds.origin.y: 0.000000
bounds.size.width: 0.000000
bounds.size.height: 0.000000
frame.origin.x: 0.000000
frame.origin.y: 0.000000
frame.size.width: 0.000000
frame.size.height: 0.000000
view coord stats:
bounds.origin.x: 0.000000
bounds.origin.y: 0.000000
bounds.size.width: 76.000000
bounds.size.height: 54.000000
frame.origin.x: -76.000000
frame.origin.y: -54.000000
frame.size.width: 76.000000
frame.size.height: 54.000000
I tried as a simple test to position the "My Location" button in the top left hand corner with:
CGRect frame = view.frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = 76;
frame.size.height = 54;
[view setFrame:frame];
but then the My Location button didn't show at all.
I have also tried small modifications to the existing values (e.g. changing frame.origin.x from -76.0 to -66.0 and can see the difference in position, so at least I'm confident I'm modifying the position of the right view. I still don't understand i) how negative coordinates work and ii) how to properly position the view in this specific scenario though. After reading the answers to this question I thought I had a reasonable grasp on view frames and bounds, but given that I haven't gotten this to work yet, apparently not.
The easiest way to solve this is to change the frame and autoresizing mask of the button right after the map view is created.
UIButton* myLocationButton = (UIButton*)[[mapView_ subviews] lastObject];
myLocationButton.autoresizingMask = UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin;
CGRect frame = myLocationButton.frame;
frame.origin.x = 5;
myLocationButton.frame = frame;
EDIT: Sorry, I placed the button in the top right corner. Updated my code to place it in the bottom left hand corner.
Note: there is currently no API from Google to get the location button. The first line may not work in future releases of the SDK.
You also should create a feature request here.
Another option is to create the button yourself and add it as a subview to the map.
The button handler code is fairly easy:
CLLocation *location = mapView_.myLocation;
if (location) {
[mapView_ animateToLocation:location.coordinate];
}
You can use the padding of the GMSMapView.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-37.81969
longitude:144.966085
zoom:4];
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
_mapView.settings.myLocationButton = YES;
_mapView.myLocationEnabled = YES;
_mapView.padding = UIEdgeInsetsMake(0, 0, kOverlayHeight, 0);
self.view = _mapView;
SWIFT 3
self._mapView.padding = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
in swift 3 xcode 8
func moveLocationButton() -> Void{
for object in mapView.subviews{
for obj in object.subviews{
if let button = obj as? UIButton{
let name = button.accessibilityIdentifier
if(name == "my_location"){
//config a position
button.center = self.view.center
}
}
}
}
}
for (UIView *object in mapView_.subviews) {
if([[[object class] description] isEqualToString:#"GMSUISettingsView"] )
{
for(UIView *view in object.subviews) {
if([[[view class] description] isEqualToString:#"UIButton"] ) {
CGRect frame = view.frame;
frame.origin.y -= 60;
view.frame = frame;
}
}
}
};
As of July 2015, this is a way to do it:
for (UIView *object in mapView_.subviews) {
if([[[object class] description] isEqualToString:#"GMSUISettingsView"] )
{
for(UIView *view in object.subviews) {
if([[[view class] description] isEqualToString:#"GMSx_QTMButton"] ) {
CGRect frame = view.frame;
frame.origin.y -= 60;
view.frame = frame;
}
}
}
};
for (UIView *object in _mapView.subviews) {
if([[[object class] description] isEqualToString:#"GMSUISettingsPaddingView"] )
{
for (UIView *settingView in object.subviews) {
if([[[settingView class] description] isEqualToString:#"GMSUISettingsView"] )
{
for(UIView *view in settingView.subviews) {
if([[[view class] description] isEqualToString:#"GMSx_QTMButton"] ) {
CGRect frame = view.frame;
frame.origin.y -= 60;
view.frame = frame;
}
}
}
};
}
}

Programmatically set UILabel has blurry text (integer frame values)

I have a view where I programmatically set a UILabel in viewDidLoad. The text on that label is blurry. The code:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self setTitle:tAddSystemScreenTitle];
CGRect rect = CGRectMake(10,0,300,80);
UILabel *messageLabel = [[UILabel alloc] initWithFrame:rect];
[messageLabel setOpaque:NO];
if (shouldShowControlForRemoteAccess) {
[messageLabel setText:kRemoteAccessInfoMessage];
[messageLabel setNumberOfLines:2];
} else {
[messageLabel setText:kOneSystemAlreadyAssociatedAlertString];
[messageLabel setNumberOfLines:4];
rect.size.height += 30;
[messageLabel setFrame:rect];
rect = dataTable.frame;
rect.origin.y += 30;
rect.size.height -= 30;
[dataTable setFrame:rect];
}
NSLog(#"x: %f, y: %f, w: %f, h: %f", messageLabel.frame.origin.x, messageLabel.frame.origin.y, messageLabel.frame.size.width, messageLabel.frame.size.height);
[messageLabel setBackgroundColor:[UIColor clearColor]];
[messageLabel setShadowColor:[UIColor blackColor]];
[messageLabel setTextColor:[UIColor blackColor]];
[messageLabel setTextAlignment:UITextAlignmentLeft];
[messageLabel setShadowOffset:CGSizeMake(0,-1)];
[self.view addSubview:messageLabel];
NSLog(#"x: %f, y: %f, w: %f, h: %f", self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
[dataTable setScrollEnabled:NO];
[messageLabel release], messageLabel = nil;
}
When I checked what the frame values were, I got the following:
x: 10.000000, y: 0.000000, w: 300.000000, h: 80.000000
Checking the same for self.view gets:
x: 0.000000, y: 20.000000, w: 320.000000, h: 460.000000
The only other questions I could find on this issue suggested that I needed integer numbers for the frame, but as you can see I already have integer numbers. I tried the solution they recommended, using CGRectIntegral(rect) to replace all the places I had just rect, but that didn't work. How do I prevent the text from blurring?
I had the same problem. In my case the reason was that I was calling setShouldRasterize on the parent view.
Perhaps it is the fact that you have black text with an ever so slightly offset black shadow, which makes it look blurry. Try removing your shadowColor and shadowOffset lines and see how it looks.

Resources