This may be too basic or require rephrasing. I am in the process of learning Swift and iOS programming and have developed a basic application that runs successfully on my iPhone 5. The app consists of a label, a button, and a UIImageView. It looks the way I want it to on my iPhone 5.
I figured most of this out by just playing around and so I am creating all these elements programatically. The code looks like this:
let banner = UILabel(frame: CGRect(x: 10, y: 10, width: 300.0, height: 75.0))
let button = UIButton(frame: CGRect(x: 45, y: 75, width: 235.0, height: 60.0))
let imageView = UIImageView(frame: CGRect(x: 22, y: 150, width: 280.0, height: 410.0))
And then I configure them in viewDidLoad to make them show stuff.
Now the question...how to I make them all the right size when running on different devices? I can load up the app on my iPad Mini but it's all scrunched over to the left of the view. So I need to do some kind of dynamic layout but not sure where to start.
All help appreciated!
Rather than creating the view sizes explicitly with initWithFrame: constructors, you can programmatically create and NSLayoutConstraints to your views to automatically layout your views, the same as if you used Auto Layout with the Interface Builder. See Apple's Auto Layout Guide for more details.
Related
I want to add an action for a custom Chromecast button.
I can use a default button (GCKUICastButton) with a default action.
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
castButton.tintColor = UIColor.gray
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
But I need to create my own view with a list of devices that can connect with Chromecast.
How to get all available Chromecast devices?
We highly recommend that you use the widgets in the Cast SDK for both the button and displaying the list of devices. You should use the various styling options to customize the widgets as needed for your branding.
I am adding a calendar to my app and thought it would be cool to mimic the format of standard iOS Calendar app as per weekday labels:
In the Calendar app, these labels (S,M,T,W,T,F,S) seem to be integrated into the navigation bar, so I was wondering if there is a way to implement this or if this is something Apple left to themselves (as there seems to be no standard way to add anything but bar button items). Mind you, these labels should be dynamic - e.g. rearrange in case of day 2 as firstWeekDay for certain Locale.
Apple proposes not to resize navigationBar itself, but remove shadow from bar and add custom view under your navigationBar.
Please refer the apple recommended approach for extended navigation bars here - https://developer.apple.com/library/content/samplecode/NavBar/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007418-Intro-DontLinkElementID_2
And your particular scenario - https://developer.apple.com/library/content/samplecode/NavBar/Listings/NavBar_ExtendedNavBar_ExtendedNavBarViewController_swift.html#//apple_ref/doc/uid/DTS40007418-NavBar_ExtendedNavBar_ExtendedNavBarViewController_swift-DontLinkElementID_13
You just need to set a view to your title view of navigationItem for example:
sampleLabel.textAlignment = .center
sampleLabel.textColor = UIColor.white
sampleLabel.font = UIFont.systemFont(ofSize: 12, weight: .medium)
sampleLabel.frame = CGRect(x: 0, y: 0, width: 40, height: 30)
sampleLabel.text = "T"
let titleView = UIView
titleView.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
titleView.addSubview(sampleLabel)
navigationItem.titleView = titleView
You can add labels to your navigationBar like sampleLabel wherever you want.
I am wondering if I can use UI elements like UIButton, UILabel in an augmented reality app with ARKit.
If you are also interested in transparency modes for that UIView subclasses try my sample https://github.com/erikhric/ar-menu
You can use different blending modes. I guess .alpha will work for your purposes.
Yes, you can use UIKit elements by adding them to a UIView that's positioned above the view displaying the AR scene (ARSKView or ARSCNView).
If you create a new project in Xcode and select the "Augmented Reality App" template, you can see that the AR content is just a view like any other UIKit view.
What worked best for me
in main.storyboard:
- delete SceneView
- add regular UIView
- add ARKit SceneKit View on top of that
- then you can add buttons, etc.
Yes you can place UI elements on top of the ARSKView or ARSCNView displaying the AR scene:
let scanningPanel = UIImageView()
scanningPanel.backgroundColor = UIColor(white: 0.33, alpha: 0.6)
scanningPanel.layer.masksToBounds = true
scanningPanel.frame = CGRect(x: -2,
y: self.sceneView.frame.height-270,
width: 178,
height: 50)
scanningPanel.layer.cornerRadius = 10
let scanInfo = UILabel(frame: CGRect(x: 8,
y: self.sceneView.frame.height-268,
width: 160,
height: 45))
scanInfo.textAlignment = .left
scanInfo.font = scanInfo.font.withSize(15)
scanInfo.textColor = UIColor.white
scanInfo.text = "SCAN A SURFACE"
Adding:
self.sceneView.addSubview(scanningPanel)
self.sceneView.addSubview(scanInfo)
Removing:
if(scanInfo.isDescendant(of: self.sceneView)) {
scanInfo.removeFromSuperview()
}
You can insert content of any view on a plane in ARKit like this:
let plane = SCNPlane(width: sceneView.bounds.width/3000,
height: sceneView.bounds.height/3000)
plane.firstMaterial?.diffuse.contents = self.anyView`
Gestures and taps are automatically sent to that view.
Try my example.
I'm having trouble figuring out how to lay out views in Swift Playgrounds for iPad, though this may also be relevant to Mac users.
The following code should create a view with a red square (also a view) that is near the edges of its' super view, but not touching them.
let v = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let sqv = UIView(frame: CGRect(x: 400, y: 400, width: 50, height: 50))
sqv.backgroundColor = .red
v.addSubview(sqv)
PlaygroundPage.current.liveView = v
The result is not what you'd expect:
I suspect I know what is going on here; live views are at a fixed size that is larger than the display area. Some characteristics of the view are ignored when it is acting as the live view. However, I can't find where this is mentioned in the documentation, which vexes me. More importantly, how do I deal with this? I would like to be able to layout simple UIs that change to fit the current size of the live view. I don't know how to address this issue without trial & error and hardcoding, which are two things I would really like to avoid.
I suspect I know what is going on here; live views are at a fixed size that is larger than the display area.
Actually it's more like the other way around. An iPad screen is 1024 points wide (in landscape orientation). The right-hand pane (where it shows your live view) is 512 points wide. The playground forces your root view (v) to fill that pane, inset by 40 points on the left, right, and top (and more on the bottom). So your root view's width is forced to 432 ( = 512 - 2 * 40), less than the 500 you specified.
Views created in code (like yours) have translatesAutoresizingMaskIntoConstraints = true, and a resizing mask of 0, which means don't adjust the view's frame at all when its parent is resized. So the playground resizes your root view to width 432, but your root view doesn't move or resize its subview (sqv).
The easiest fix is to set the autoresizing mask of the subview to express your intent that it remain near the right and bottom edges of the root view. That means it should have flexible top and left margins:
let v = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let sqv = UIView(frame: CGRect(x: 400, y: 400, width: 50, height: 50))
sqv.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin]
sqv.backgroundColor = .red
v.addSubview(sqv)
PlaygroundPage.current.liveView = v
Result:
let sqv = UIView(frame: CGRect(x: UIScreen.mainScreen().bounds.width-50-1, y:400, width: 50, height: 50))
The above code places your subview 1 point away from the right of the main view. Try changing the value 1 after 50 in x to desired value.
I am just testing some animation of "falling" views. I want to simulate leafs that fall from the sky. I have made this really simple code which is unfinished, but was used to check if I was doing it right.
However, should the "falling" views have auto layout constraints attached to them? Is it bad to just add views to the screen like this when the rest of the view is done with auto layout? I am using Swift 2 and iOS 9.
let rectangleView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
rectangleView.backgroundColor = UIColor.redColor()
backgroundView.addSubview(rectangleView)
UIView.animateWithDuration(10, delay: 0, options: [UIViewAnimationOptions.CurveEaseIn], animations: {
rectangleView.center = CGPoint(x: rectangleView.center.x, y: 300)
}, completion: nil)
If your views are moving freely on the screen, then I don't see any reason to use auto layout constraints.
There is no issue adding a subview to a UI that uses auto layout and animating it yourself, as you are doing. Not everything on the screen has to be managed by auto layout.