IOS center bottom position view - objective-c

I do the following to a loading animation, to place it at the bottom center of the screen.
CGPoint bottomCenter = CGPointMake((self.imageView.bounds.size.width / 2), (self.imageView.bounds.size.height * 0.8));
self.activityView.center = bottomCenter;
(imageView is the full screen splash image)
If the orientation is portrait, it is positioned perfectly, however turning on its side, in landscape or upside down portrait and the animation ends up miles away :S
Does anyone know the correct way to position this loading animation, its for the splash screen.

use UIDeviceOrientationIsLandscape(deviceOrientation) and UIDeviceOrientationIsPortrait(deviceOrientation) instead of deviceOrientation==X

First, look at tkanzakic's answer.
Second, don't use screen bounds, orientate the view by its parent view. If you put your view to the bottom of your parent view and you set the autoresizing mask correctly, everything will be done automatically - no need to check device orientation.

Try this code
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGPoint bottomCenter;
if (deviceOrientation == 1) {
bottomCenter = CGPointMake((screenBounds.size.width / 2), (screenBounds.size.height * 0.8));
}
else if (deviceOrientation == 4) {
bottomCenter = CGPointMake((screenBounds.size.width / 2), (screenBounds.size.height * 0.8));
}
In landscape mode you are taking wrong width and height
In landscape mode width and height also change.

Related

Pinch Gesture Zoom only Zooms UIImage from Upper Left Corner

I am fairly new to this and I'm trying to use pinch gestures to zoom in on a UIImage and be able to zoom into any specific part of the image. However, when I zoom it only zooms from the upper left corner of the UIView. So I only get to see the upper left corner of the image zoomed in. I'd like to be able to zoom/pan the image similar to how the Photos app works. Here is my code so far:
In ViewDidLoad:
...
// Load the image to be viewed into the UIImage
self.theImage.image = self.theNewImage;
UIPinchGestureRecognizer *pinchGestRecog = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(twoFingerPinch:)];
// ADD GESTURE RECOGNIZER TO THE VIEW
[theImage addGestureRecognizer:pinchGestRecog];
// ALLOW USER INTERACTION ON THE VIEW
[theImage setUserInteractionEnabled:YES];
// SET IMAGE ZOOM SCALE LIMITS
imageCurrentScale = 1.0;
imageMaxScale = 2.0;
imageMinScale = 0.5;
And then in my twoFingerPinch method:
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)aPinchGesture
{
if (imageCurrentScale * [aPinchGesture scale] > imageMinScale && imageCurrentScale * [aPinchGesture scale] < imageMaxScale) {
imageCurrentScale = imageCurrentScale * [aPinchGesture scale];
CGAffineTransform zoomTransform = CGAffineTransformMakeScale(imageCurrentScale, imageCurrentScale);
[[aPinchGesture view] setTransform:zoomTransform];
}
[aPinchGesture setScale:1.0];
}
Is panning somehow the answer? I'm not really sure how panning works.
Any suggestions? Thanks.
The reason why you zoom to your upper left corner is because the center of your scale transformation is the UIView.layer.anchorPoint which is default the upper left corner (0,0).
If you want to zoom correctly you somehow have to figure out the center of your pinch gesture and then set your anchorPoint to that position.
But you shouldn't do that anyway. The recommended way to zoom into a UIImageView is to place the the image view into a UIScrollView and set the contentSize and maximumZoomScale and minimumZoomScale values accordingly.
Set yourself as the delegate of your UIScrollView and return the UIImageView in the viewForZooming delegate method.
The scrollview will handle the pinching and zooming for you.

iOS: Orientation get future self.view.bounds

Background: I wanted to animate the change in my content along with the orientation. My content position is relative to the self.view.bounds.
Problem: In order to animate the content along with the bounds, I would need to know what would the bounds of the view be at the end. I can hard code it but I hope to find a more dynamic way.
Codes: So all animation takes place in willRotateToInterfaceOrientation as per following:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//centering the image
imageView.frame = CGRectMake(self.view.bounds.origin.x + (self.view.bounds.size.width - image.size.width)/2 , self.view.bounds.origin.y + (self.view.bounds.size.height - image.size.height)/2, image.size.width, image.size.height);
NSLog(#"%d",[[UIDevice currentDevice] orientation]);
NSLog(#"%f", self.view.bounds.origin.x);
NSLog(#"%f", self.view.bounds.origin.y);
NSLog(#"%f", self.view.bounds.size.width);
NSLog(#"%f", self.view.bounds.size.height);
}
The bounds are before the orientation change. Thus, this only works if the transformation is 180 degrees. If I were to use didRotateFromInterfaceOrientation, the animation will be after the orientation change which looks awful.
Use willAnimateRotationToInterfaceOrientation:duration: instead. This method gets called from within the rotation animation block, and all the bounds have been set correctly at this point. Docs.
If you want it dynamic then when you initialize imageView, set the autoresizingMask property so that when the imageView's superview resizes on the rotate the margins can auto resize themselves...
imageView = //init imageView
imageView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
//addtional config
This means you only need to set the frame once then the imageView will always adjust itself to stay in the middle.
Check out the UIView class reference http://developer.apple.com/library/ios/ipad/#documentation/uikit/reference/uiview_class/uiview/uiview.html to see what else you can do with the autoresizingMask property
If I'm understanding you correctly, you just need to swap the X/Y coordinates and width/height in you're CGRectMake, to get your future layout for a 90 degree change. If it's 180 degree change, then it's the same as current
CGRectMake(self.view.bounds.origin.y + (self.view.bounds.size.height - image.size.height)/2 , self.view.bounds.origin.x + (self.view.bounds.size.width - image.size.width)/2, image.size.height, image.size.width);

Get center screen position of view in landscape orientation

At the moment I have an UIImageView inside a window. When the scene loads I save its position with:
imageView.center
The user can drag it around. On some occasions the item gets animated back to its original position which has been saved. This all works fine, when I hold the IPad vertically.
When I hold it horizontally though I cant move it back to that position, because in landscape mode I cant use the position which was saved in vertical orientation mode. this is because in Interface Builder I set the item to get auto sized relative to the borders (meaning if the item was in the center, then rotating the IPad it still stays in center)
So my question is: How can I get the correct original position the item would have in landscape orientation?
I tried to calculate the position by hand like this:
- (CGPoint)getHorizontalCoordinatesForPoint:(CGPoint)point
{
CGSize size = [[UIScreen mainScreen]applicationFrame].size;
CGFloat relativeX = (point.x / (size.width));
CGFloat relativeY = point.y / (size.height);
CGFloat horizontalScreenX = relativeX * (size.height);
CGFloat horizontalScreenY = relativeY * (size.width);
return CGPointMake(horizontalScreenX, horizontalScreenY);
}
but this position is a bit off. I think it is because I dont take into account the size of the navigation bar. Is there some converting function in ios which already does what I want?
Don't.
Rather, instead of saving [imageView center] when the scene loads, save it at key points:
-touchesBegan:withEvent: (or, if you are using gesture recognizers, in the gesture recognizer callback).
-didRotateFromInterfaceOrientation:
The minor complication is what happens if a user, say, is working in landscape, quits the app, rotates the portrait, and relaunches the app. In this case I would start the app in landscape and let the autorotation to portrait kick in and correct your center point.

Center a MacGLView in a Window

I have an cocos2D app that runs in 4/3 ratio and I want to enter fullscreen mode resizing the view to maintain the aspect ratio without showing black bars at screen sides. So, when the app enters fullscreen, I do this:
NSRect aFrame=[[NSScreen mainScreen] frame];
[glView_ setFrameSize:NSMakeSize(aFrame.size.width,aFrame.size.height*1.2)];
This way I got fullscreen wide but (as I wanted) the ratio is untouched. My problem now is that the glview is not centered on screen. It extends from left bottom point so I got my game unevenly clipped (all clipping is done at top). I've trying to use [glview setFrameOrigin] and similar to select the visible portion of the view without success.
I just want to displace my view a certain number of pixels down so it shows the center area of whole view. Is it possible?.
Thanks in advice.
You are changing the dimensions of glView_, but not its origin.
NSRect aFrame=[[NSScreen mainScreen] frame];
CGFloat x = 0.0f;
CGFloat y = aFrame.size.height;
CGFloat width = aFrame.size.width;
CGFloat height = aFrame.size.height * 1.2f;
glView_.frame = NSRectFromCGRect((CGRectMake(x, y/2 - height / 2, width, height));

Scrollable UINavigationBar similar to Mobile Safari

My application uses a UINavigationController and the final view (detail view) lets you view an external website within the application using a UIWebView.
I'd like to free up some additional screen real estate when the user is viewing a webpage and wanted to emulate how Safari on iPhone works where their URL bar at the top scrolls up and off the screen when you're viewing content in the UIWebView that's below the fold.
Anyone have ideas on how to achieve this? If I set the navigationBarHidden property and roll my own custom bar at the top and set it and a UIWebView within a UIScrollView then there are scrolling issues in the UIWebView as it doesn't play nicely with other scrollable views.
Based on #Brian suggestion I made this code:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat height = navigationBar.frame.size.height;
CGFloat y = scrollView.bounds.origin.y;
if (y <= 0) {
CGRect frame = navigationBar.frame;
frame.origin.y = 0;
navigationBar.frame = frame;
} else if (tableView.contentSize.height > tableView.frame.size.height) {
CGFloat diff = height - y;
CGRect frame = navigationBar.frame;
frame.origin.y = -y;
navigationBar.frame = frame;
CGFloat origin = 0;
CGFloat h = height; // height of the tableHeaderView
if (diff > 0) {
origin = diff;
h = y;
}
frame = tableView.frame;
frame.origin.y = origin;
frame.size.height = tableView.superview.frame.size.height - origin;
tableView.frame = frame;
CGRect f = CGRectMake(0, 0, tableView.frame.size.width, h);
UILabel* label = [[UILabel alloc] initWithFrame:f];
tableView.tableHeaderView = label;
[label release];
}
}
My code has a UITableView but should work with any scrollable component. If you have other components than the navigationBar and the UIScrollView subclass, you should change the way the height of the scrollable component is calculated. Something like this:
frame.size.height = tableView.superview.frame.size.height - origin - otherComponentsHeight;
I needed to add a dumb tableHeaderView to have the desired behaviour. The problem was that when scrollViewDidScroll: is called the content has an offset, but the apparience in Mobile Safari is that the content is not scrolled until the navigationBar fully disappears. I tried first changing the contentOffset.y to 0, but obviously it didn't work since all the code relies on the scrolling mechanism. So I just added a tableHeaderView whose height is exactly the scrolled offset, so the header is never really seen, and the content appears to not scroll until the navigationBar fully disappears.
If you don't add the dumb tableHeaderView, then the scrollable component appears to scroll behind the navigationBar.
With the tableHeaderView, the scrollable component is actually scrolling (as seen in the scrollbar), but since there is a tableHeaderView whose height is exactly the same than the scrolled offset, the scrollable content appears to not be scrolling until the navigationBar fully disappears:
Have a delegate for the scrolling events in the UIWebView and when you initially start scrolling the UIWebView, have the UIWebView increase in height and have it's Y position decrease at the same time while simultaneously shifting the nav bar up in the Y direction. Once the nav bar has been completely shifted out of view, stop increasing the size of the UIWebView and just allow normal scrolling to occur.
This will give the illusion of the nav bar being part of the UIWebView as it scrolls off the screen.
Also, you'll need to do the reverse when you are scrolling in the opposite direction and are reaching the top of the content of the UIWebView.
Can't give you a straight answer, but have a look at iWebKit. Maybe that provides a solution. The demo, at least, contains a "full screen" item.