Set view position to top right programmatically in cocoa touch - objective-c

I need to make sure that one view A (size: 200x200) is always aligned to top right corner inside second view B (full screen size). I want to make sure that view A stays in that place regardless of device orientation. Truth is I have no problem with this when using interface builder to position the views but I need to construct this programmatically. I suppose I should use some autoresizing settings, could you tell me which one is supposed to align the view to top right corner of its superview?

UIView parentView //your full screen view
UIView view //the 200x200 view
[parentView addSubview:view];
CGRect frame = view.frame;
//align on top right
CGFloat xPosition = CGRectGetWidth(parentView.frame) - CGRectGetWidth(frame);
frame.origin = CGPointMake(ceil(xPosition), 0.0);
view.frame = frame;
//autoresizing so it stays at top right (flexible left and flexible bottom margin)
view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin
That positions the view on top right and set's the autoresizing mask so it stays at that position.

Related

Scrollview vertical only with fixed width in Autolayout

In swift how can I set the width of the scroll view to be the width of the screen size?
I tried setting right leading and trailing bounds, but my aspectscalefill image keeps stretching the entire frame.
I am trying to force the view to be the width of the screen and allow vertical scrolling only.
If you want to make a scroll view with auto layout try this. No code at all so you will have to drag things out of the library to the right of Xcode.
In your view controller drag and place the scroll view size it to whatever you want but it looks like you want to make it the size of the screen. Pin all edges to the edges of the view controller. Pin trailing, leading, top, and bottom.
Now, instead of placing your items in the scroll view, place another view in the scroll view. With this new view you will place all of your items. You will most likely have to move the view up or down to place them all and resize the view. You can then place whatever constraints you want on your items. When all items are in their place, set the frame of the new view back to x = 0 and y = 0.
You will then place constraints as follows. Select the new view and pin to top, bottom, trailing, and leading and then center in container. This will make a constraint that is vertical with some negative number. In the storyboard outline select this constraint and set it to zero.
You will now be able to scroll vertically. Let me know if you have any questions.
I created a single view application, and added a UIScrollView in the storyboard with four constraints (top, left, right, bottom). And I add the following code in the viewDidLoad(). Everything works just fine. My image is only scrolling vertically, but not horizontally. No additional settings are needed.
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Just as an example, I make a size with same with of the view
// and twice the height of the view.
let size = CGSizeMake(
self.view.frame.size.width,
self.view.frame.size.height * 2);
// Load an image and make a image view
let image = UIImage(named: "im.jpg")!
let imageView = UIImageView(image: image)
imageView.frame = CGRect(
origin: CGPoint(x: 0, y: 0),
size: size);
imageView.contentMode = UIViewContentMode.ScaleToFill;
// Add the image view to scroll view
scrollView.addSubview(imageView)
scrollView.contentSize = size;
}
Your problem i caused by the fact that you add your elements to the scrollView from the storyBoard.
In the storyBoard you need:
1) Add the scrollView, if you need to be in the width of the screen then set it's trailing and leading spaces to superView to 0
2) uncheck the "allow horizontal scrolling" in the attribute inspector
In your code
1) set the scrollView's contentSize to what ever size you want it to be.
1.1) in your code you need to set the size of the contentView like so
scroller.contentSize = CGSizeMake(your width, your height);
This is a very important step, the scrollView will not be able to scroll if you don't set the size. Think about the scrollView as the window and the contentView as the view. If the contentView if the same size as the scrollView then the scrollView can't scroll anywhere (all of the contentView fits into the scrollView) in order to create the scrolling you need to make the contentView bigger then the scrollView itself
2) start adding your elements to the scrollView's contentView by calling
[scroller addSubView:<your view>];
this will add your views to the scrollView's contentView and will be

UITextView not resizing correctly

I have a view that has a table view on the top, and a scroll view below the table view.
When I press the resize bar button item, I want to hide the table view and maximize the scroll view. I got the scroll view and table view to animate correctly, but I am trying to resize the UITextView inside the scroll view to take advantage of the extra screen space.
Whenever I calculate the resize, the UITextView goes to the top left corner of the screen, and I'm not sure why. I am not even modifying the X and Y, just the height.
CGRect newDesFrame = descriptionTextView.bounds;
newDesFrame.size.height = newDesFrame.size.height + tableViewFrame.size.height;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.5];
self.scrollView.frame = scrollFrame;
self.descriptionTextView.frame = newDesFrame;
[UIView commitAnimations];
I am not sure why this happens. Does the descriptionTextView.bounds get messed up since it's in a UIView inside a UIScrollView? It seemed that, when I do a NSLog of the X and Y of the scroll view, it's 0,0. It's weird since it's not at 0,0 in the superview, or in the view. How do I fix this?
descriptionTextView is most likely jumping to the top left because you are, in fact, changing the origin (x and y). You are starting with:
CGRect newDesFrame = descriptionTextView.bounds;
Getting the bounds of that text view will give you a CGRect with an origin of 0,0, as 'bounds' gives you the view's rectangle in its own, local coordinate space.
Try this instead:
CGRect newDesFrame = descriptionTextView.frame;
This will give you the view's rectangle in its superview's coordinate space, including the actual origin.
It happens because you are doing
self.descriptionTextView.frame=newDesFrame ( which is Bounds property, not frame!! To read about differences Link)
Solution:
self.descriptionTextView.bounds=newDesFrame

Black box over MKMapView

I have an MKMapView and another UIView subclass that is overlaid on top of the map. The custom view is transparent (I use it to overlay an inner shadow around the edge of the map). Now when I drop a pin on the map view a small black square shows up over the pin. It seems to disappear and change size randomly too. I can't take a screenshot of it because for some reason it doesn't appear in screenshots. I know it's related to the custom view that's overlaid on the map because when I remove it everything works fine.
Any ideas?
EDIT: As requested here's the screenshot
and the code for the shadow overlay view:
self.layer.cornerRadius = 8.0f;
self.layer.borderColor = [UIColor colorWithWhite:0.8f alpha:0.6f].CGColor;
self.layer.borderWidth = 1.0f;
self.layer.masksToBounds = YES;
self.clipsToBounds = YES;
self.layer.shadowOffset = CGSizeMake(0, 1);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 1.0;
I place the shadow overlay view in IB and that code is in the drawRect method of the view subclass.
Put your non-clipped shadow view inside another view with clipping on, this will clip the shadow on the outside of the box.

Full-screen UIImageView aligning to bottom

With the following code:
UIImageView *largeImageView = [[UIImageView alloc] initWithImage:theImage];
[largeImageView setContentMode:UIViewContentModeScaleAspectFit];
largeImageView.frame = [[UIScreen mainScreen] applicationFrame];
[viewController.view addSubview:largeImageView];
viewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewController animated:YES];
I would expect the image to be at the top of the View, not the bottom. I double-checked the origin x and y, and they are 0,0.
Here is a screenshot: http://cl.ly/8F3J
Thanks to Tommy for providing some thinking out loud and debugging help, I figured out what I was doing wrong. I changed around the order of operations and added the imageview as a subview after I pushed the viewcontroller on the nav stack. This fixed the issue as my view controller had it's new view from the nav controller.
largeImageView is a subview of viewController.view, so its coordinates are relative to that of its superview. Probably you want something more like:
// the bounds of viewController.view contain its correct size, but
// have an origin of (0, 0)
largeImageView.frame = viewController.view.bounds;
[viewController.view addSubview:largeImageView];
What's probably happening at the minute is that you're getting a frame much larger than the view controller's view size, then the fact that UIViewContentModeScaleAspectFit will be adding some space at the top and bottom of the view as necessary (assuming your image is proportionally wider than the target view) is pushing the image off the bottom of the screen.

resizing an NSPanel to fit a dynamic NSMatrix and a button

I have an NSMatrix that is filled dynamically with some form items. Now, I can conveniently call [theMatrix sizeToCells] and then pass it into the panel to be displayed.
Now, I want the NSPanel object which contains this NSMatrix to resize to wrap nicely around it. The NSPanel also has a button at the bottom which should be under the NSMatrix.
I have been trying many things with getting bounds and setting frames and have been having much confusion.
Is there any standard or correct way of sizing a panel to it's contents?
As a side question: Does a frame's origin refer to it's top left or bottom left? Is it always consistent?
Thanks
The origin of an NSPanel/NSWindow frame is always the bottom-left corner, it's measured from the screen origin.
Whether the origin of a view is the top left or bottom left depends on whether or not its superview is flipped. Flipped views have their bounds origin in the top left.
To do what you want, you need to get the frame size of the NSMatrix, then recalculate the layout of the panel.
Something like this (written in here, untested!):
//NSMatrix* matrix;
//NSPanel* panel;
CGFloat panelMargin = 10.0;
CGFloat matrixBottomMargin = 30.0;
[matrix sizeToCells];
NSRect matrixFrame = [matrix frame];
NSRect panelFrame = [panel frame];
NSSize newPanelSize = NSMakeSize(NSWidth(matrixFrame) + 2.0 * panelMargin,
NSHeight(matrixFrame) + 2.0 * panelMargin + matrixBottomMargin);
CGFloat yDelta = newPanelSize.height - NSHeight(panelFrame);
panelFrame = NSMakeRect(panelFrame.origin.x,
panelFrame.origin.y - yDelta,
newPanelSize.width,
newPanelSize.height);
[panel setFrame:panelFrame display:YES];