Resizing NSWindow don't autoresize its contentView correctly - swift

I have an NSWindow with it's contentView. In the awakeFromNib() of the NSWindow I have the following code:
override func awakeFromNib()
{
super.awakeFromNib()
/// Customize Window through XIBs
self.title = "Main Window"
let screenFrame = NSScreen.main?.frame
let windowPercentage: CGFloat = 0.9;
let offset: CGFloat = (1.0 - windowPercentage) / 2.0;
let windowFrame: NSRect = NSRect(x: (screenFrame?.width)! * offset, y: (screenFrame?.height)! * offset, width: (screenFrame?.width)! * windowPercentage, height: (screenFrame?.height)! * windowPercentage )
self.setFrame(windowFrame,display: true,animate: true)
self.backgroundColor = NSColor.lightGray
self.isRestorable = true
// Customize contentView
let viewPercentage: CGFloat = 0.6
self.contentView?.setFrameSize(NSSize(width: self.frame.size.width * viewPercentage, height: self.frame.size.height))
self.contentView?.setFrameOrigin( NSMakePoint( ( (self.frame.width) - (self.contentView?.frame.width)! )/2, ( (self.frame.height) - (self.contentView?.frame.height)!)/2) )
self.contentView?.autoresizingMask = [.width, .height, .minXMargin,.maxXMargin,.maxYMargin,.minYMargin]
}
I am trying to set up the contentView in the center and with a percentage of its NSWindow frame but it's failing when i resize the window. As soon as I start to resize the Window the contentView it's not resizing correctly, as you can see from the following image(the second one):
Image one
Image two
Should I override the resize(withOldSuperviewSize:) method to achieve this? (also the autoresize from interface builder don't resolve the issue)

You shouldn't attempt to change the size of the content view like that. I don't believe it's supported. The window controls the content view's size.
If you want a view of your own to occupy only a portion of the window's content area, you should add your view as a subview of the content view.

Related

Change content size UIScrollView dynamically

I have a scroll view, when the view is first loaded, the size is set dynamically, but when I click on the button, the internal size of my elements changes and I need to change the internal size of the scroll, but it does not change. Someone knows how to fix it?
DispatchQueue.main.async {
var contentRect = CGRect()
for view in self.scrollView.subviews {
contentRect = contentRect.union(view.frame)
self.scrollView.contentSize = contentRect.size
}
}
If you really don't want to use auto-layout / constraints, you can call this function each time you add (or remove) a subview from the scroll view, or after you've changed the size(s) of the subview(s):
func updateContentSize() -> Void {
// this will get the right-edge of the right-most subview
let width = scrollView.subviews.map {$0.frame.maxX}.max() ?? 0.0
// this will get the bottom-edge of the bottom-most subview
let height = scrollView.subviews.map {$0.frame.maxY}.max() ?? 0.0
// set the contentSize
scrollView.contentSize = CGSize(width: width, height: height)
}
This solution is for auto-layout/constraints.
You need a reference constraint to manipulate the height of the inner container view of the scrollview.
private var _constraintInnerContainerScroll:NSLayoutConstraint?
You need to set the initial height of the inner container view, suppose 700.0
private let _containerViewHeightFixed : CGFloat = 700.0
then you need to save the reference
_constraintInnerContainerScroll = _containerView.heightAnchor.constraint(equalToConstant: _containerViewHeightFixed)
_constraintInnerContainerScroll?.isActive = true
You initial view is setup and ready, now suppose you add 2 more subview of height 100.0 each, now your new inner container view height should be 700.0+200.0 = 900.0
if let const1 = _constraintInnerContainerScroll{
const1.constant = _containerViewHeightFixed + 200.0
UIView.animate(withDuration: 0.5) {
self?._containerView.layoutIfNeeded()
}else{
print("constraint reference not saved")
}
let me know if this works for you, or if this can be improved.

UIScrollview constraints for different devices

Currently, I have the following codes to make UIScrollView work for iPhone that I have set it up in the main storyboard.
var images: [String] = ["image1", "image2"]
var frame = CGRect(x:0,y:0,width:0,height:0)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
pageControl.numberOfPages = images.count
for index in 0..<images.count {
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
let imgView = UIImageView(frame: frame)
imgView.image = UIImage(named: images[index])
self.scrollView.addSubview(imgView)
}
scrollView.contentSize = CGSize(width: (scrollView.frame.size.width * CGFloat(images.count)), height: scrollView.frame.size.height)
scrollView.delegate = self
}
I am trying to make a horizontal scrollview in xcode but when I run the project on iPad, the scrollview changes to the screen size but not the images. I looked up solutions online by adding views to the scroll view but it does not work. I am trying to make the images resize accordingly to the scrollview size.
Quick fact: Images are stored in Assets.xcassets.
Any help would be very much appreciated. Thanks!

How to give an imageView in swift3.0.1 shadow at the same time with rounded corners

I want to give an imageView a shadow at the same time with rounded corners,but I failed.
Here is my solution
Basic idea :
Use an Extra view (say AView) as super view of image view (to those views on which you are willing to have shado) and assign that view class to DGShadoView
Pin Image view to AView (that super view)from left, right, top and bottom with constant 5
Set back ground color of the AView to clear color from storybosrd's Property inspector this is important
Inside idea: Here we are using a Bezier path on the Aview nearly on border and setting all rounded corner properties and shadow properties to that path and we are placing our target image view lie with in that path bound
#IBDesignable
class DGShadoView:UIView {
override func draw(_ rect: CGRect) {
self.rect = rect
decorate(rect: self.rect)
}
func decorate(rect:CGRect) {
//self.backgroundColor = UIColor.clear
//IMPORTANT: dont forgot to set bg color of your view to clear color from story board's property inspector
let ref = UIGraphicsGetCurrentContext()
let contentRect = rect.insetBy(dx: 5, dy: 5);
/*create the rounded oath and fill it*/
let roundedPath = UIBezierPath(roundedRect: contentRect, cornerRadius: 5)
ref!.setFillColor("your color for background".cgColor)
ref!.setShadow(offset: CGSize(width:0,height:0), blur: 5, color: "your color for shado".cgColor)
roundedPath.fill()
/*draw a subtle white line at the top of view*/
roundedPath.addClip()
ref!.setStrokeColor(UIColor.red.cgColor)
ref!.setBlendMode(CGBlendMode.overlay)
ref!.move(to: CGPoint(x:contentRect.minX,y:contentRect.minY+0.5))
ref!.addLine(to: CGPoint(x:contentRect.maxX,y:contentRect.minY+0.5))
}
}
Update
Extension Approach
There is another Approach. Just Make a class with empty and paste Following UIImageView Extension code, Assign this subclass to that ImageView on which you shadow.
import UIKit
class DGShadowView: UIImageView {
#IBInspectable var intensity:Float = 0.2{
didSet{
setShadow()
}
}
override func layoutSubviews()
{
super.layoutSubviews()
setShadow()
}
func setShadow(){
let shadowPath = UIBezierPath(rect: bounds)
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0.0, height: 0.3)
layer.shadowOpacity = intensity
layer.shadowPath = shadowPath.cgPath
}
}
The solution is to create two separate views. One for the shadow and one for the image itself. On the imageView you clipToBounds the layer so that the corner radius is properly added.
Put the imageView on top of the shadowView and you've got your solution!

Redraw view inside of self.view on viewDidLoad() in swift?

I'm working on an app that has a view that is positioned in various places depending on the screen size of it. The size depends on the device. I chose the size of the iPhone 5S. My app will run on an iPad.
See how was the Swift code:
class Main: UIViewController {
#IBOutlet var viewRect: UIView!
let DeviceHeigth:CGFloat = 1136 / 2
let DeviceWith:CGFloat = 640 / 2
override func viewDidLoad() {
super.viewDidLoad()
calcviewRectViewInit()
}
func calcviewRectViewInit(){
let space:CGFloat = 40
var frame: CGRect = viewRect.frame
frame.size.height = DeviceHeigth
frame.size.width = DeviceWith
frame.origin = CGPoint(x: toolView.frame.width + space, y: space)
viewRect.frame = frame
}
When you start, the Rect view is not positioned in the sizes and positions - by code. The viewDidLoad is not redrawn the view at runtime.
My question is: How can redraw the view (viewRect) when starting the app?
You should use the superview's frame as a reference.
For example:
var frame: CGRect = viewRect.frame
frame.size.height = self.view.frame.height / 2
frame.size.width = self.view.frame.width / 2
I referenced self.view instead of just view for clarity. UIViewController has the view property. This can be used where you are attempting to reference the device size.
You should also make sure you have the frame set correctly for the toolView prior to building this frame.
Additionally, I would recommend looking at Auto Layout for this particular problem. It was designed to aid in supporting user interfaces on various size screens. Below is a link to more information about it.
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/index.html

adding NSImageView to NSScrollView

I have an image with a dimension of about 200x2000 pixels. I want to display the image centered in a 200x200 rectangle but I want to be able to move it up and down. Best I can figure I need to add an NSImageView to an NSScrollView but I can't figure out how or even if this is the best way. This is my first day of OS X development...
After some googling I found this from which I was able to come up with this
class MasterViewController: NSViewController {
var Photo: NSImageView!
#IBOutlet var scroll: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
var imageRect: NSRect
self.Photo = NSImageView.init()
self.Photo.image = NSImage.init(named:"horizon")
imageRect = NSMakeRect(0.0, 0.0, self.Photo.image!.size.width, self.Photo.image!.size.height)
print("image size", imageRect)
self.Photo = NSImageView(frame: imageRect)
self.Photo.setBoundsSize(NSSize(width: imageRect.width, height: imageRect.height))
self.Photo.imageScaling = NSImageScaling.ScaleNone
self.scroll.setFrameSize(NSSize(width: imageRect.width,height: imageRect.width))
self.scroll.hasVerticalScroller = true
self.scroll.hasHorizontalScroller = true
self.Photo.setFrameSize(CGSize(width: imageRect.width,height: imageRect.width))
self.scroll.documentView = self.Photo
//print(self.scroll.documentView?.frame)
//self.scroll.setC contentSize = NSSize(width: 200, height: 2000)
//self.Photo.image = NSImage.init(named:"bezel")
//self.scroll.addSubview(self.Photo)
}
but I can't get the image to show up inside the scrollview
#lusher00: in your example, you initialize twice self.Photo, first with an init() and then with (frame: imageRect), this probably explains why image don't show up.
You could set the imageView as the documentView of the NSScrollView, as below:
#IBOutlet var scrollView: NSScrollView!
var imageRect: NSRect
// Initialize below the imageView image with appropriate content (to adapt)
imageView.image = NSImage.init(named:"horizon")
imageRect = NSMakeRect(0.0, 0.0, imageView.image!.size.width, imageView.image!.size.height)
imageView.setFrameSize(CGSize(width: imageRect.width, height: imageRect.height))
imageView.imageScaling = NSImageScaling.ScaleNone
scrollView.documentView = imageView
scrollView.hasVerticalScroller = true
scrollView.hasHorizontalScroller = true
Just add the image view as a subview of the scrollview.
scrollView.addSubview(imageView)
You can set the position of the imageview, which will position it inside the scrollview.
The scrollview needs to know how large its content size is to enable scrolling of that area. So dont forget to update the contentSize property of the scrollview.
E.g. adding the imageView of 200x200 to the scrollView with a frame of 200x200. Setting the contentSize to 400x400 and calling imageView.center = scrollView.center, will center the image and allow some scrolling around the image, within the 200x200 visible frame of the scrollview.
You can also get the current offset of the scrollView by checking contentOffset.
If you need to track as the user scrolls, you can use scrollViewDidScroll. Check the docs for the scrollview for some other options.