Centering buttons programatically in Swift - swift

I am trying to center Google Sign In and Sign Out buttons programmatically. In order to put both of them in the third quarter. I create 2 views that I wanted to put buttons to their center, in Storyboard.
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
let gSignIn = GIDSignInButton(frame: CGRect(x: 0, y: 0, width: loginView.frame.size.width, height: loginView.frame.size.height))
loginView.addSubview(gSignIn)
gSignIn.center = loginView.center
let gSignOut = UIButton(frame: CGRect(x: 0, y: 0, width: signOutView.frame.size.width, height: signOutView.frame.size.height))
gSignOut.backgroundColor = UIColor.white.withAlphaComponent(0)
gSignOut.setTitle("Sign Out", for: .normal)
gSignOut.setTitleColor(UIColor.red, for: .normal)
gSignOut.addTarget(self, action: #selector(self.signOut(_:)), for: .touchUpInside)
gSignOut.center = signOutView.center
self.signOutView.addSubview(gSignOut)
As you can see, also I am trying to resize buttons according to view size which helps me to resize buttons depend on device size.
Here is the second half of my storyboard.
Here is the simulator screen when I run the code.
Thanks.

Use auto-layout instead of setting frame.center, it will be more flexible.
Autolayout goes like below code.
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
let gSignIn = GIDSignInButton(frame: CGRect(x: 0, y: 0, width: loginView.frame.size.width, height: loginView.frame.size.height))
gSignIn.translatesautoresizingmaskintoconstraints = false
loginView.addSubview(gSignIn)
NSLayoutConstraint.activate([
gSignIn.leftAnchor.constraint(equalTo: loginView.leftAnchor),
gSignIn.rightAnchor.constraint(equalTo: loginView.rightAnchor),
gSignIn.topAnchor.constraint(equalTo: loginView.topAnchor),
gSignIn.bottomAnchor.constraint(equalTo: loginView.bottomAnchor)
])

Related

Add drop shadow to xib view in Swift

I have added a card view from a Xib file which when tapped it slides from bottom-up to display the view.
I have am trying to customised the view and a drop shadow to the view which is not working.
The cornerRadius works fine otherwise.
func setupCard() {
menuCardVC = MenuCardVC(nibName:"MenuCardVC", bundle:nil)
menuCardVC.view.layer.shadowOpacity = 0.50
menuCardVC.view.layer.shadowRadius = 12
menuCardVC.view.layer.shadowColor = UIColor.black.cgColor
menuCardVC.view.layer.shadowOffset = CGSize.zero
menuCardVC.view.layer.cornerRadius = 25
self.addChild(menuCardVC)
self.view.addSubview(menuCardVC.view)
menuCardVC.view.frame = CGRect(x: 0, y: self.view.frame.height - cardHandleAreaHeight, width: self.view.bounds.width, height: cardHeight)
menuCardVC.view.clipsToBounds = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(VenueDetailsVC.handleCardTap(recognzier:)))
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(VenueDetailsVC.handleCardPan(recognizer:)))
menuCardVC.handleArea.addGestureRecognizer(tapGestureRecognizer)
menuCardVC.handleArea.addGestureRecognizer(panGestureRecognizer)
}//end setupCard
Remove the below line of code,
menuCardVC.view.clipsToBounds = true
Since your view hierarchy is simple you could use the following technique. Also, you don't need to use clipsToBounds.
let superview = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
superview.backgroundColor = .white
let subview = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
subview.backgroundColor = .red
// First provide the corner radius.
subview.layer.cornerRadius = 8
// Then provide the shadow parameters.
subview.layer.shadowOpacity = 1
// ...
// Do not clip to bounds since it will clip the shadow.
// ...
superview.addSubview(subview)

Align Drop Down Menu Title to prevent overlapping of other buttons

I have the below image where the title of the drop down menu title is overlapped with other buttons. How to solve this issue?
Code:
func createDropDownMenu() {
// create the drop down menu
let title = prepareNavigationBarMenuTitleView()
prepareNavigationBarMenu(title)
updateMenuContentOffsets()
}
func prepareNavigationBarMenuTitleView() -> String {
// Both title label and image view are fixed horizontally inside title
// view, UIKit is responsible to center title view in the navigation bar.
// We want to ensure the space between title and image remains constant,
// even when title view is moved to remain centered (but never resized).
titleView = DropDownTitleView(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
titleView.addTarget(self,
action: #selector(DocumentViewController.willToggleNavigationBarMenu(_:)),
for: .touchUpInside)
titleView.addTarget(self,
action: #selector(DocumentViewController.didToggleNavigationBarMenu(_:)),
for: .valueChanged)
titleView.titleLabel.lineBreakMode = NSLineBreakMode.byClipping
titleView.titleLabel.numberOfLines = 2
titleView.titleLabel.textColor = UIColor.black
titleView.title = currentNode.title
navigationItem.titleView = titleView
return titleView.title!
}
I had to set the frame of the TitleLable and set the numberOfLines = 0 to solve my problem.
Code:
titleView.titleLabel.frame = CGRect(x: 0, y: 0, width: 600, height: 80)
titleView.numberOfLines = 0
titleView.titleLabel.text = currentNode.title

Creating a button image with padding bottom in Swift

I'm creating a system of Filters.
I'm trying to do that:
Currently I'm using the setBackgroundImage func, and I don't have this little rect below the picture:
filterButton.setBackgroundImage(imageForButton, for: .normal)
I tried functions like this one:
filterButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
But it's not effective if I keep the setBackgroundImage func.
If I use setImage(), the results is good but the click is not effective any more.
filterButton.setImage(imageForButton, for: UIControlState.normal)
Do you have an idea to do what I would like ?
The full snippet:
for i in 0 ..< CIFilterNames.count {
itemCount = i
// Button properties
let filterButton = UIButton(type: .custom)
// filterButton.frame = CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight)
filterButton.frame = CGRect(x: xCoord, y: yCoord, width: buttonWidth, height: buttonHeight)
filterButton.tag = itemCount
filterButton.addTarget(self, action: #selector(self.filterButtonTapped(_:)), for: .touchUpInside)
// filterButton.layer.cornerRadius = 6
// filterButton.clipsToBounds = true
let ciContext = CIContext(options: nil)
let coreImage = CIImage(image: originalImage.image!)
let filter = CIFilter(name: "\(CIFilterNames[i])" )
filter!.setDefaults()
filter!.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData = filter!.value(forKey: kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData, from: filteredImageData.extent)
let imageForButton = UIImage(cgImage: filteredImageRef!)
filterButton.backgroundColor = UIColor.red
filterButton.setImage(imageForButton, for: UIControlState.normal)
//filterButton.imageEdgeInsets = UIEdgeInsets(top: 0,left: 0,bottom: 15,right: 0)
//filterButton.setBackgroundImage(imageForButton, for: .normal)
filterButton.setTitle("A\(i)", for: .normal)
// filterButton.backgroundImage.contentMode = .scaleAspectFill
filterButton.setTitleColor(UIColor(red: 22 / 255, green: 21 / 255, blue: 22 / 255, alpha: 1), for: .normal)
filterButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
filterButton.titleEdgeInsets.top = 140
// Add Buttons in the Scroll View
xCoord += buttonWidth + gapBetweenButtons
filtersScrollView.addSubview(filterButton)
}
It looks like you are trying to do everything in a single UIButton. I would suggest creating a custom element to handle this.
There are a few ways you could setup a custom UI element with the functionality that you want:
Use a UILabel to display the "A1" label with the colored background and display the image itself in a separate UIImageView. These could be overlaid with a invisible UIButton to receive the touchUpInside event and pass to your controller.
Alternatively, you could create a custom UIControl add add a UILabel and UIImageView as subviews. Disabling userInteraction on the subviews should allow the UIControl to receive the touch events. This could be contained in a single reusable class as if it's one UI element.

iOS Swift: Install and Unistall views programmatically

How to install and uninstall views programmatically?
Example
Im my application I have a StackView containing three different Views: Character, Starship and Vehicle.
Now, I would like that at a certain condition, just one View will appear and the other two won't.
I'm not saying hiding and showing, but installing and uninstalling. Why? because if I keep my views installed my Xcode crash.
Any tips?
I believe the answer you're looking for is here - https://stackoverflow.com/a/36712325/2463875
If You install or uninstall view from storyboard, It is equivalent to add/remove view.
I am not sure if I understand it 100% correctly.. But if you want to add views to a stackview programatically, you can do it kind of the following way. You need to connect the UIStackView to your ViewController to have access to it. There you can add your UIViews depending on a condition.
I've created a playground example. So you can just copy it and run it in a playground and it will also show it visually to you. To make it easier, I've used UILabels. But it's pretty much the same with UIViews.
import UIKit
import PlaygroundSupport
class TestViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "Test"
self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
self.view.backgroundColor = UIColor.brown
let stackview = UIStackView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
stackview.axis = .vertical
stackview.distribution = UIStackViewDistribution.fillEqually
let text = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
text.text = "Hello, i am a label"
let condition = true
if condition {
let text2 = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
text2.text = "Hello, i am another label"
stackview.addArrangedSubview(text2)
}
stackview.addArrangedSubview(text)
self.view.addSubview(stackview)
}
}
let testController = TestViewController()
PlaygroundPage.current.liveView = testController.view
testController

Menu system for Games in SpriteKit

I've looked at a few different post surrounding menu systems in SpriteKit and nothing really focusses on how to implement from start to finish (a basic play button starting the game, background and then sharing icons).
The reason I am looking is that I am a beginner and in the process of building my first basic game. I have used a few of these guides and none seem to give a proper walk through.
Thought it would be good to create a post for all beginners to start out. I have attempted some actual code but it hasn't been successful (quite a few errors though I can post if anyone is interested in seeing what NOT to do).
Anyway, here goes nothing😊 Thanks in advance all, lets see how we can get it done!
well, i believe this is a good question and setting up something as an answer here is not a bad idea. i've setup a starting menu with a title and three buttons in this very simple menu. that can be modified to the desired result later. first of all create a new file for starting menu by adding the file through project pane on the left. then create a spritekitScene also with the same name (startMenu or whatever you want to name it) then do the same for the settings and also credits or any other item you want to add to the start menu.
the next step is the change the entry point of the game from game scene to start menu in view controller swift. change the game scene to whatever you named your menu in this line if let scene = GameScene(fileNamed:"GameScene") to if let scene = StartMenu(fileNamed:"StartMenu") that will push the start menu rather than the game scene. go the start menu and add the following codes for creating a title and buttons to the view. i created the buttons and the text and added separate functions for each for the ease of following up, and then at the end you add the functions for the selector so when the buttons are pressed the new scene gets pushed. you can also add a return button to those scenes or do whatever else you want. so here is the complete start menu code:
import Foundation
import SpriteKit
class StartMenu : SKScene {
var btnPlay : UIButton!
var btnSettings : UIButton!
var btnCredits : UIButton!
var gameTitle : UILabel!
override func didMoveToView(view: SKView) {
// self.backgroundColor = UIColor.orangeColor()
setUpTitleText()
setupButtonPlay()
setupButtonSettings()
setupButtonCredits()
}
func setUpTitleText(){
gameTitle = UILabel(frame: CGRect(x: 0, y: 0, width: view!.frame.width, height: 300))
gameTitle.textColor = UIColor.blackColor()
gameTitle.font = UIFont(name: "Futura", size: 50)
gameTitle.textAlignment = NSTextAlignment.Center
gameTitle.text = "Game Title"
//gameTitle.backgroundColor = UIColor.whiteColor()
self.view?.addSubview(gameTitle)
}
func setupButtonPlay(){
btnPlay = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnPlay.center = CGPoint(x: view!.frame.size.width / 2, y: 250)
btnPlay.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnPlay.setTitle("Play", forState: UIControlState.Normal)
btnPlay.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnPlay.backgroundColor = UIColor.grayColor()
btnPlay.addTarget(self, action: #selector(StartMenu.playTheGame), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnPlay)
}
func setupButtonSettings(){
btnSettings = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnSettings.center = CGPoint(x: view!.frame.size.width / 2, y: 350)
btnSettings.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnSettings.setTitle("Settings", forState: UIControlState.Normal)
btnSettings.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnSettings.backgroundColor = UIColor.grayColor()
btnSettings.addTarget(self, action: #selector(StartMenu.pressTheSettings), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnSettings)
}
func setupButtonCredits(){
btnCredits = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnCredits.center = CGPoint(x: view!.frame.size.width / 2, y: 450)
btnCredits.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnCredits.setTitle("Credits", forState: UIControlState.Normal)
btnCredits.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnCredits.backgroundColor = UIColor.grayColor()
btnCredits.addTarget(self, action: #selector(StartMenu.pressTheCredits), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnCredits)
}
func playTheGame(){
self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = GameScene(fileNamed: "GameScene"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
func pressTheSettings(){
self.view?.presentScene(TheSettings(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = TheSettings(fileNamed: "TheSettings"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
func pressTheCredits(){
self.view?.presentScene(TheCredits(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = TheCredits(fileNamed: "TheCredits"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
}
in this scenario i have hard coded the titles and the buttons, but you can add your own images if you want. this is just a simple way of creating a menu but there are many other ways to do this. as you go along you can build your own in anyway you like.
good luck.