I have a problem when i want to add a 3D subview to my controller view. I can't see the 3D subview. Is the code of GameControllerView class :
override func viewDidLoad() {
super.viewDidLoad()
println("Start the game")
// Model
cubeData = CubeData()
/*
let viewTest = UIView(frame: self.view.frame)
self.view = viewTest
*/
// 3D view position
let sizeScnView = CGSize(width: 350.0, height: 350.0)
let centerView = CGPoint(x: CGRectGetMidX(self.view.frame) - sizeScnView.width/2, y: CGRectGetMidY(self.view.frame) - sizeScnView.height/2)
scnView = GameSceneView(frame: CGRect(origin: centerView, size: sizeScnView))
// add 3D view
self.view.addSubview(scnView)
// don't allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = false
// Start Accelerometer
self.motionManager = CMMotionManager()
self.startAccelerometer()
timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true)
}
With this code i can't see my GameSceneView which is a subclass of SCNView (3D view). But if I delete comments of the viewTest variable (just below cubeData) my GameSceneView is displayed but without the content of my controller view.
Question : Why 3D subview can't appear on the controller view ?
EDIT : I just noticed that the 3D view is behind the controller view background. How can I add my 3D view over the background contained in view controller ?
If your superview is GPU-rendered (i.e. a SceneKit or SpriteKit view), there may be issues with having GPU-rendered subviews. One solution may be to make what's currently your view controller's view into a subview, so that your scnView is a sibling view to it, and use insertSubview:aboveSubview or a related method to layer them.
Related
In Apple's official Exhibition app demo, there's such usage in viewDidLoad() in the ImageViewerController.swift
/*
Turn on translatesAutoresizingMaskIntoConstraints, Interface Builder
turns this off for all views in a nib. The `NSScrollView` and `NSClipView`
expect to be able to control their documentView via modifying its `frame`.
*/
imageView.translatesAutoresizingMaskIntoConstraints = true
I noticed that in the xib file, the imageView already has constrains set up. When the line of code is commented out, the view still works.
To better understand the code from the demo, I created a minimal project with only a NSScrollView added under the default view controller's view. Here the NSImageView is created programmatically. If the constrains in h and v are activated, the window will be very big and unresponsive to resizing and dragging.
class ViewController: NSViewController {
#IBOutlet weak var scrollView: NSScrollView!
#IBOutlet weak var clipView: NSClipView!
override func viewDidLoad() {
super.viewDidLoad()
let path = "/Library/Desktop Pictures/Snow.jpg"
let url = URL(fileURLWithPath: path, isDirectory: false)
let image = NSImage(contentsOf: url)
let imageView = NSImageView(image: image!)
imageView.translatesAutoresizingMaskIntoConstraints = false
clipView.addSubview(imageView)
let h = NSLayoutConstraint.constraints(
withVisualFormat: "H:|[imageView]|",
options: NSLayoutConstraint.FormatOptions(rawValue: 0),
metrics: nil,
views: ["imageView" : imageView])
let v = NSLayoutConstraint.constraints(
withVisualFormat: "V:|[imageView]|",
options: NSLayoutConstraint.FormatOptions(rawValue: 0),
metrics: nil,
views: ["imageView" : imageView])
clipView.documentView = imageView
// NSLayoutConstraint.activate([h, v].flatMap({$0}))
}
}
My questions are:
Why and how do the constrains in my project cause the problem, while the constrains in the demo don't.
Are the constrains in the official demo necessary?
I want to make a scroll view programmatically in xcode and want to add anchor constraints using safe area layout guide Auto Layout. And want to add some text views button and map init but could not find any proper way to do this. I have tried many codes. What is the proper code for this?
Please try below code for programmatically create Scroll view and add UIView inside XCode
Swift 4.0
import UIKit
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let myView: UIView = {
let view = UIView()
view.backgroundColor = .yellow
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// add the scroll view to self.view
self.view.addSubview(scrollView)
// constrain the scroll view to 8-pts on each side
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
//Frame for UIView here
myView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
scrollView.addSubview(myView)
}
}
I have set up my UIImageView using the below setup. I am trying to draw on the view but can not get anything to appear. I am new to Xcode and want my view to automatically change depending on what the screen size is. When I have used the storyboard I could not figure out how to get the view to change with the screen size and/or rotation. As a result I figured it would be easier to make that happen in the ViewController.swift file. When the program wasn't working I tried to see if the view was appearing on the screen. When I made one of the views red, I still could not see anything on the screen. I am very confused. I am open to any feedback. I appreciate you taking time to read this and am looking forward to assistance.
Thanks,
T
import UIKit
import CoreGraphics
class ViewController: UIViewController {
var ResultImageView = UIImageView ( frame: UIScreen.mainScreen().bounds)
var DrawingImageView = UIImageView ( frame: UIScreen.mainScreen().bounds)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
ResultImageView.userInteractionEnabled = true
ResultImageView.backgroundColor = UIColor.redColor()
DrawingImageView.userInteractionEnabled = true
}
I think the problem is you have to create the imageview in viewDidAppear if you're setting the screen size, because the screen size hasn't been set and orientated where you're setting it. Try the below and hope this issue gets resolved soon :)
var ResultImageView = UIImageView()
var DrawingImageView = UIImageView()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
ResultImageView = UIImageView (frame: self.view.frame)
DrawingImageView = UIImageView (frame: self.view.frame)
ResultImageView.userInteractionEnabled = true
self.view.addSubview(ResultImageView)
self.view.addSubview(DrawingImageView)
ResultImageView.backgroundColor = UIColor.redColor()
DrawingImageView.userInteractionEnabled = true
}
I have a UIScrollView inside a UIViewController (subclassed by ImageViewController). The ViewController itself is part of a NavigationController's stack. Now, apart from having a navigation bar, I want the ScrollView to take all of the available room on the screen. The UIImageView inside the scrollview should then fill the available room of the scroll view. You can see the current state at the bottom of this posting.
class ImageViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
var imageView: UIImageView?
var image: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
if let image = image {
imageView = UIImageView(image: image)
if let imageView = imageView {
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image.size
let scaleHeight = scrollView.frame.size.height / scrollView.contentSize.height
let scaleWidth = scrollView.frame.size.width / scrollView.contentSize.width
let minimumScale:CGFloat = min(scaleHeight, scaleWidth)
let maximumScale:CGFloat = max(scaleHeight, scaleWidth)
scrollView.minimumZoomScale = minimumScale
scrollView.maximumZoomScale = maximumScale
scrollView.zoomScale = maximumScale
}
}
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
}
The code leaves me with unnecessary borders (left, right, top). How do I get rid of them?
EDIT: With #Bxtr's suggestion and another stackoverflow thread I was able to remove the borders left and right to the scroll view. After some more digging I found out that by deactivating Adjust Scroll View Insets, the image inside the scroll view can be correctly vertically positioned. Still, I do not get the reason for the vertical misplacement in the first place...
Have you checked the margin/padding values, because it kinda looks so (same size on left and right border). If it is not the case, could you please also post your xml file of the activity so we can have every part of the puzzle to help you ?
scrollView.contentSize = image.size;
you have to tweek this line. You are explicitly setting scroll view content size to the image size. You have to set content size to fit the Width of Screen.
You can use a UIView in UIScrollView, and that UIView contains UIImage.
You need to set constraints properly.
After some more digging I found out that by deactivating Adjust Scroll
View Insets, the image inside the scroll view can be correctly
vertically positioned. Still, I do not get the reason for the vertical
misplacement in the first place...
The reason is that the view controller's automaticallyAdjustsScrollViewInsets property is by default YES, the following is from apple documentation:
automaticallyAdjustsScrollViewInsets
A Boolean value that indicates
whether the view controller should automatically adjust its scroll
view insets.
Default value is YES, which allows the view controller to adjust its
scroll view insets in response to the screen areas consumed by the
status bar, navigation bar, and toolbar or tab bar. Set to NO if you
want to manage scroll view inset adjustments yourself, such as when
there is more than one scroll view in the view hierarchy.
Besides setting automaticallyAdjustsScrollViewInsets = No, you can pin the scrollView to the topLayoutGuide (instead of to the top of the viewController's view) when using autoLayout.
I have a simple view that displays an NSBezierpath. On mouseDown inside the path, the path's fill color sets to yellow and the view redraws. On mouseDown outside the path, the path's fill color sets to blue and the view redraws.
In my storyboard, I have a single window controller with a window content segue to a view controller. The view, customview class HeartView (below) fills the entire view controller.
Everything works fine until the user resizes the window vertically. After that, the view exhibits bizarre behavior: mouseDown no longer works everywhere inside the path, the recolor sometimes happens on mouseDown outside the path, and the path sometimes (but not always) doesn't completely fill. I think something is going on in the superview, but I don't know what.
import Cocoa
class HeartView: NSView {
var mouseLocation : NSPoint = NSZeroPoint
func drawObject(){
//Create an empty Bezier path
let aBezier : NSBezierPath = NSBezierPath()
aBezier.moveToPoint(CGPoint(x: 176.95,y: 44.90))
aBezier.curveToPoint(CGPoint(x: 166.71,y: 145.89),
controlPoint1: CGPoint(x: 76.63,y: 76.78),
controlPoint2: CGPoint(x: 82.59,y: 206.70))
aBezier.curveToPoint(CGPoint(x: 176.95,y: 44.90),
controlPoint1: CGPoint(x: 237.55,y: 224.76),
controlPoint2: CGPoint(x: 276.83,y: 95.98))
aBezier.closePath()
if (aBezier.containsPoint(NSMakePoint(mouseLocation.x, mouseLocation.y))){
NSColor.yellowColor().setFill()
NSColor.greenColor().setStroke()
} else {
NSColor.blueColor().setFill()
NSColor.orangeColor().setStroke()
}
aBezier.fill()
aBezier.lineWidth = 2.0
aBezier.stroke()
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
drawObject()
}
override func mouseDown(theEvent: NSEvent) {
mouseLocation.x = theEvent.locationInWindow.x
mouseLocation.y = theEvent.locationInWindow.y
self.setNeedsDisplayInRect(self.frame)
}
}
I found the answer in Lucas Derraugh's video on Mouse Events (Cocoa Programming L27). Turns out, I was capturing the mouseDown event in the superview's coordinate system. In the mouseDown event, I used "locationInWindow," which is what caused the strange behavior. I changed the method to:
override func mouseDown(theEvent: NSEvent) {
var viewPoint:NSPoint = self.convertPoint(theEvent.locationInWindow, fromView: nil)
mouseLocation.x = viewPoint.x
mouseLocation.y = viewPoint.y
self.needsDisplay = true
}
to convert from the window's coordinate system to the view's. Things now work well after any window resize event.