How do I alter the position of a UIImage inside a UIImageView - image

I have a UIImage called image I want to change the position of it inside the imageView so it can be dragged down slightly, roughly 30px. Can some one tell me how to do it? This is where I am up to but its not coming out correct.
var image = UIImage()
var imageView = UIImageView(frame: CGRectMake(0, 0, view.frame.size.height * 0.22, view.frame.size.height * 0.22))
imageView.center = CGPointMake(self.view.center.x, view.frame.size.height * 0.414)
imageView.image = self.image
imageView.layer.cornerRadius = imageView.frame.size.width / 2
imageView.layer.borderWidth = 2.0
imageView.layer.borderColor = UIColor(red: 254.0/255, green: 216.0/255, blue: 0/255, alpha: 1.0).CGColor
imageView.clipsToBounds = true
imageView.layer.contentsRect = CGRectMake(0, 20, imageView.frame.size.width, imageView.frame.size.height) //This is where I have being trying to do it but no success.
imageView.contentMode = .ScaleAspectFill
view.addSubview(imageView)

Short answer: You don't.
What you would do is add the image view as a subview of another view. The trivial way to do this would be to put the image view in a scroll view, constrained so that the only place it can scroll is down, and only slightly. Then you could achieve the scrolling with zero code.
EDIT:
This isn't really a coding problem - it's more of an Interface Builder problem. You need to set up a scroll view.
A scroll view is a view that lets you look at a portion of a larger view.
You can think of a scroll view like a piece of paper with a rectangular hole in it. You put a bigger piece of paper under it (The scroll view's content view) and you can slide the bigger piece of paper around and view different parts of it through the hole.
Here's how you would set it up.
Drag a scroll view onto your view controller. Size it and add constraints to it to position it where you want. If you want your image view to be 300x300 points in size, for example, and want to be able to drag it up or down by 20 points, then make the scroll view 20 points taller. (w: 300, h: 320)
Select the view inside the scrollview and set it's width to the same width as it's scrollview, but 20 points taller than the scroll view. (w: 300, h: 340). Add constraints to lock it's height and width.
Now you have a scroll view that's big enough for a 300x300 point image, with 20 points of total white space at the top and bottom.
You've created a content view that's 20 points bigger than that, so it can slide up or down by 20 points in the scroll view.
Drag your 300x300 point image view into the view inside the scroll view, assign an image to it, and add constraints to lock it's size and center it horizontally and vertically in it's superview.
The final step is to set the content size of the scroll view. Normally you just set a scroll view's content size to the size of it's content view. You can do that by adding this bit of code to your view controller's viewDidLoad:
(Assuming you've connected an outlet to your scrollview that's called theScrollView)
//Get the first (and only) subview of the scrollView.
let subview = theScrollView.subviews[0] as! UIView;
//Make the scroll view's contentSize the same size as the content view.
theScrollView!.contentSize = subview.bounds.size;
It's also possible to set the content size of the scroll view without any code at all. You'd use a feature of IB (Interface Builder) called "User Defined Runtime Attributes". Here's how you'd do that: (If you use this approach don't add the code above to viewDidLoad)
Select the scroll view in IB.
Press command-option 3 to select the "identity inspector".
In the section headed "User Defined Runtime Attributes", tap the plus sign on the left. Edit the Key Path to "contentSize" (all lower case except the "S" in "Size". That's very important.) Press enter to change the key path. Then tap on the "type" column and select "size". The value field will show "{0,0}". Enter your desired content size: ("{300,340}" in the example above.)
What this does is tell IB "At runtime, look for a property called "contentSize" in the selected object (the scroll view.) Set that property to the specified value of type CGSize.
Once you're done your IB "identity inspector" should look like this:
Note that if you get a key name wrong when using "User Defined Runtime Attributes" then the app crashes when you display that view controller, with a very cryptic message.
By default scrollviews let you "overshoot" when dragging their contents around, and then bounce back into place when you let go. You can turn that feature off by unchecking the "Bounce" checkbox in the IB "Attributes Inspector" (command option 4)

You shouldn't do that. But if you want to you can play with anchorPoint property of backing layer of UImageView. link
Note: Keep in mind any layout process may alter this property later.

Related

How do I make NSScrollView size its document view for the total size of its contents using constraints?

Say I have a Mac app with a window containing an NSScrollView. When added to a storyboard or nib file, the scroll view contains a clip view (NSClipView) and an NSView that is the scroll view's document view.
I want to add some content to this document view (say, two labels arranged vertically) and set up constraints such that the scroll view will scroll as it needs to in order to reveal all the content. So:
Pin the top, leading, and trailing of the upper label to those if its superview (the document view)
Pin the top of the lower label to the bottom of the upper label
Pin the leading, trailing, and bottom of the lower label to those of its superview (the document view)
Add a custom view to the document view, pin its bottom, left, and right edges to superview, and constrain its width to a constant (the width of the window) and its height to 0 to define the scroll view's scrollable content width
At this point, if I set the text of the labels to something long enough to overrun the height of the window, I'd expect the scroll view to allow the user to scroll to reveal the rest of the content. But it doesn't - it just elastic-scrolls vertically, and the text is cut off. Even if I set the content compression resistance to 1000 on both of the labels.
What am I missing here?
Sample app here: https://github.com/tomhamming/MacScrollTester

ScrollView with embedded StackView issue

I have a scrollView with a stackView placed in it. The scrollView is constrained to the rootview. The stack view will show a xib view.
The xib views are all different lengths.
The xib views are labeled simpleVC0 and simpleVC1. The length of the simpleVC0is 2500 and the length of simpleVC1 is 1000.
My problem is that when the xib views are presented in the stack view the length of the scrollView does not change to the length of the presented xib view.
It is like the xib view is presented but the scroll view is locked at a specific length.
Here is simpleVC0 xib view. followed by it when run. When I try to scroll it doesn't allow me to scroll to the bottom of the xib view. it seems to cut the xib view off at a certain length.
Am right in saying that this is possibly an issue that may have to be resolved in code? or can it it solved souled by the constraints.
I have tried auto layout constraints however they have not worked.
I have constrained the scrollView to the rootview on all four sides.
When the root view is loaded the xibs are established using the following code:
//Different subViews for ingredients and steps
if counter == 0 {
simpleViewX = SimpleVC0().view
simpleViewY = SimpleVC1().view
stack.addArrangedSubview(simpleViewX)
stack.addArrangedSubview(simpleViewY)
}
The views are the hidden shown by changing the value of the segmented view controller. Shown below:
#IBAction func tabselected(_ sender: Any) {
switch (sender as AnyObject).selectedSegmentIndex {
case 0:
simpleViewY.isHidden = true
simpleViewX.isHidden = false
break
case 1:
simpleViewX.isHidden = true
simpleViewY.isHidden = false
break
case 2:
//calledvideo in array is the value of the counter.
calledVideo = vids[counter]
geturl()
break
default:
break
}
}
To use a UIStackView with a UIScrollView you need to allow the stack view to expand its height based on its content.
When laying it out in storyboard, give the stack view a height constraint (to satisfy IB's requirements), but give that height constraint a low Priority.
Then, when adding arranged subviews, the stack view will grow vertically.
Here's a complete example, based on the images you've shown: https://github.com/DonMag/XIBsInScrollView
You have to modify the contentSize property of your scrollView in the code. I don’t know how to deal with it with storyboards, but you can make an outlet of your scrollView and calculate the new height each times it changes (each time you add something or remove something in it)
scrollView.contentSize = CGSize(width:yourNewW, height:yourNewH)

Centering view in scroll view

I have an NSView embedded inside a NSScrollView.
When changing the magnification in my app I'm changing the view's frame by adjusting the constraints and calling layoutSubtree:.
Now I'd like to center the same area of the view after changing the embedded view's size.
The following bits of code should be doing the trick -
the scrollers actually look updated, i.e. they expand and stick to the same position. However the scroll view doesn't seem to know about the changed position.
When starting to scroll the (updated) view manually the scroll bar positions 'jump' from the position changed via code to the actual position that's reflecting the view's scroll position.
It feels like the inverse of reflectScrolledClipView: is required after setting the scrollers via code..
Pseudocode:
double hScrollPos = NSScrollView.horizontalScroller.doubleValue;
double vScrollPos = NSScrollView.verticalScroller.doubleValue;
[view updateFrameSizeAndStuff];
[view invalidateIntrinsicContentSize];
// this seems to early though:
NSScrollView.horizontalScroller.doubleValue = hScrollPos;
NSScrollView.verticalScroller.doubleValue = vScrollPos;

iOS fixed width dynamic height scrollview with autolayout in xib

I was creating a scrollview contains an image view and a dynamic height label,
here's my hierarchy in xib file:
-> view (originally existed view when xib file created )
--> scroll view
---> content view
----> image + label (dynamic height depend on its content)
I set the content view's height depend on the label's height
,and then set the scroll view's content size(scrollable area) to the content view's frame size
I expect the content view and the scroll view both has equal width to the top view
(top view's width is flexible when device got rotated, and also are the content view & scroll view's)
and only the vertical direction is scrollable.
yet I totally have no idea dealing with the autolayout,
once I set the content view's constraints to the top view, the scrolling becomes disable,
but after I remove all constraints the content view'd be scrolled like a bouncing block...
(sorry for not providing any picture but only description for my question due to low reputation)
been mad about this for a whole day
any help would be appreciated.

NSScrollView with auto layout not resizing until first manual window resize

I've got an OSX Cocoa app that has been built programatically (i.e., not with a NIB/XIB), which I'm trying to lay out using auto layout - but I'm getting some odd behaviour when the window first displays.
My main content is an NSView that holds has a collection of 100 NSButtons as subviews, laid out vertically. The buttons are all constrained relative to the NSView and each other; both the NSView and all the NSButtons have translatesAutoresizingMaskIntoConstraints=NO set. I believe the code for the content view is good (i.e., no ambiguous layouts, etc), because if I set the main window's contentView to the NSView, the buttons display as expected.
However, if I set the main window's contentView to be an NSScrollView, and set the documentView of the NSScrollView to be the NSView, I get display problems.
On first display, I get a blank window - no scroll bars, nothing:
The NSScrollView has translatesAutoresizingMaskIntoConstraints=NO. For debug purposes, I've also set the background colour of the NSScrollView to blue so that I can confirm what is being laid out where - but there's no blue shown anywhere.
But, as soon as I resize the window, the layout kicks in, and I get an NSScrollView the full size of the main window, with blue background, and scrollbars as expected:
I've read some references that suggest the problem is the lack of constraints on the clipView that is part of the NSScrollView. On that basis, I've tried setting up constraints binding [NSScrollView contentView] to [NSScrollView documentView] in the vertical and horizontal directions (with constant 0, multiplier 1, on the left, right, top and bottom). When I do this, the NSScrollView is now visible on first display, but it's the wrong size. The scroll doesn't scroll the full height of the internal content - the scrollable content scrolls as if it is the same size as the visible window. Lastly, the content overlaps the titlebar of the window:
Again, as soon as I resize the window, the constraints kick in, and the window displays as I'd expect (see the previous screenshot). So, I take it the extra constraints don't hurt, but they don't seem to be adding anything, either.
Further confusing matters - if I leave the buttons off altogether, and just use an empty NSView with no subviews as the content view, I get a full window of blue on startup, as I'd expect.
So - what's going on here? It feels like I'm missing a call to force the evaluation of constraints on the buttons; is that the case, or is something else going on here?
For those interested - here's my sample code. It's not Objective C - it's Python - but the language binding can convert Python method names into Objective C messages; the mapping to native ObjectiveC API should be obvious:
app = NSApplication.sharedApplication()
app.setActivationPolicy_(NSApplicationActivationPolicyRegular)
main_window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
NSMakeRect(100, 100, 640, 480),
NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask,
NSBackingStoreBuffered,
False)
scrollview = NSScrollView.alloc().init()
scrollview.setHasVerticalScroller_(True)
scrollview.setHasHorizontalScroller_(True)
scrollview.setAutohidesScrollers_(True)
scrollview.setBorderType_(NSNoBorder)
scrollview.setTranslatesAutoresizingMaskIntoConstraints_(False)
scrollview.backgroundColor = NSColor.blueColor()
container = NSView.alloc().init()
container.setTranslatesAutoresizingMaskIntoConstraints_(False)
buttons = [
NSButton.alloc().init()
for b in range(0, 100)
]
for i, button in enumerate(buttons):
button.setBezelStyle_(NSRoundedBezelStyle)
button.setButtonType_(NSMomentaryPushInButton)
button.setTitle_(get_NSString('Button %s' % i))
button.setTranslatesAutoresizingMaskIntoConstraints_(False)
container.addSubview_(button)
if i == 0:
container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
button, NSLayoutAttributeTop,
NSLayoutRelationEqual,
container, NSLayoutAttributeTop,
1, 50,
))
else:
container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
button, NSLayoutAttributeBottom,
NSLayoutRelationEqual,
buttons[i-1], NSLayoutAttributeBottom,
1, 50,
))
container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
button, NSLayoutAttributeLeft,
NSLayoutRelationEqual,
container, NSLayoutAttributeLeft,
1, 50,
))
container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
button, NSLayoutAttributeRight,
NSLayoutRelationEqual,
container, NSLayoutAttributeRight,
1, -50,
))
container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
buttons[-1], NSLayoutAttributeBottom,
NSLayoutRelationEqual,
container, NSLayoutAttributeBottom,
1, -50,
))
scrollview.setDocumentView_(container)
main_window.setContentView_(scrollview)
main_window.makeKeyAndOrderFront_(None)
app.activateIgnoringOtherApps_(True)
app.run()
I've worked out an answer - I'm not entirely happy with it, but it seems to work.
There are certain Cocoa widgets that don't deal well with autolayout - in particular, I've found problems with top level NSWindows and NSTabViewItems; I'm guessing other widgets might also be affected. Essentially, these are "container" widgets that have a top level "view" that must be set. If the "contained" widget is an NSScrollView (which itself will contain other widgets), the "container" widget has difficulty establishing a size for the "contained" scroll view.
The fix is to re-enable translatesAutoresizingMaskIntoConstraints for the view that will be used as the "contained" widget. In the example provided, the object scroll_view created on line 10 is the "contained" widget; the boolean value of the call to setTranslatesAutoresizingMaskIntoConstraints on line 15 should be True, not False.
These problems get better with more recent versions of OS/X - Mavericks doesn't have a problem with NSWindow, but it still has a problem with NSTabViewItem. However, it doesn't seem to do any damage to turn on translatesAutoresizingMaskIntoConstraints on newer versions of OS X; all you're losing it the theoretical purity of a 100% autolayout solution.
Look at Apple's 2012 developer conference videos about Auto Layout for information about using Auto Layout in code.
Simply use in Interface Builder or in code the approach I recorded in this video tutorial:
How to use NSScrollView with Auto Layout
This is the approach I used in this video:
Window -- set delegate and IBOutlet property
ScrollView -- fixed edges, no border, don't draw background
documentView -- fixed edges 0, then another trailing and bottom, clipView ≥ 0 #499 and clipView ≤ 0 #501 for both trailing and bottom constraints to documentView
label and text field in horizontal stack view, in vertical stack view
vertical stack view fixed edges default, then another bottom, bottom ≤ default #499 and ≥ default #750
horizontal stack view leading and trailing fixed 0
label and text field align Y center to horizontal stack view
text field top and bottom and trailing 2 #750, width ≥ 100, height ≥ 22
subsequent horizontal stack views leading and trailing fixed, align text field leadings
The real issue is that some of your controls are fixing the size of the view and thus for the window. For example, if you have only one view, say view1 inside your viewcontroller's view, and:
set leading/trailing/top/bottom to the main view and
view1.height = 300,
this will make your window size to be fixed to 300 and thus not resizeable.

Resources