how do I make another button appear if I pressed one button in swift - swift

I am trying to make a game where if I press a button it can spawn another button in another area so you can click and keep doing that, every time you press the button you should get a point. I don't know how to spawn another button when I pressed one button.
// this is the code
var monkeyPosition : Int = 1
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.addSubview(makeButtonSpawn())
view.addSubview(makeButtonSpawn2())
}
#IBAction func monkeyPlayer(_ sender: UIButton) {
if sender.tag == 1 && (monkeyPosition == 1) {
makeButtonSpawn2().isHidden = false
}
}
func makeButtonSpawn() -> UIButton {
let monkey = UIButton(type: UIButton.ButtonType.system)
//Set a frame for the button. Ignored in AutoLayout/ Stack Views
monkey.frame = CGRect(x: 30, y: 30, width: 90, height: 90)
monkey.backgroundColor = UIColor.blue
makeButtonSpawn().isHidden = true
return monkey
}
func makeButtonSpawn2() -> UIButton {
let monkey = UIButton(type: UIButton.ButtonType.system)
//Set a frame for the button. Ignored in AutoLayout/ Stack Views
monkey.frame = CGRect(x: 80, y: 80, width: 90, height: 90)
monkey.backgroundColor = UIColor.blue
makeButtonSpawn2().isHidden = true
return monkey
}

Create instance variables for your buttons, then you will be able to access them from places in your class. Also you can set its properties inside variable closure instead of declaring method
class ViewController: UIViewController {
var button1: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 30, y: 30, width: 90, height: 90)
button.backgroundColor = .blue
return button
}()
var button2: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 80, y: 80, width: 90, height: 90)
button.backgroundColor = .blue
button.isHidden = true
return button
}()
}
Next, you need to add your buttons as subviews to main view and you need to add target for them
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.addSubview(button1)
view.addSubview(button2)
button1.addTarget(self, action: #selector(button1Pressed(_:)), for: .touchUpInside)
button2.addTarget(self, action: #selector(button2Pressed(_:)), for: .touchUpInside)
}
#objc func button1Pressed(_ sender: UIButton) {
}
#objc func button2Pressed(_ sender: UIButton) {
}
Finally, you can unhide second button when first button is pressed
#objc func button1Pressed(_ sender: UIButton) {
if monkeyPosition == 1 {
button2.isHidden = false
}
}

Related

NSCollectionViewItem button action No effect

Clicking the button has no effect
I hope someone with good intentions can help me see why
Below is my code
class cell_word_list_1: NSCollectionViewItem {
static let item = NSUserInterfaceItemIdentifier(rawValue: "cell_list_id_1")
override func viewDidLoad() {
super.viewDidLoad()
}
override func loadView() {
let rootView = NSView()
rootView.wantsLayer = true
rootView.layer?.backgroundColor = #colorLiteral(red: 0.5725490451, green: 0, blue: 0.2313725501, alpha: 1)
let button = NSButton()
button.frame = NSRect(x: 0, y: 0, width: 100, height: 100)
button.action = #selector(click)
rootView.addSubview(button)
self.view = rootView
}
#objc func click() {
print("------> button click")
}
}
Without a target the action is sent to the first responder and up the responder chain. This doesn't work because the item is not in the responder chain. Solution: set the target of the button:
button.target = self

create a if statement where only one button at a time can have a border

I want my swift code to use a if statement or another sequence to only display a border on one of the buttons if click at a time. So a border can only be seen on one button at a time that button would be the last one pressed. I know I could say layer.border with 0 on each button that should be selected but I want to see if there is a more efficient way to do this.
import UIKit
class ViewController: UIViewController {
var ba = UIButton()
var bb = UIButton()
var bc = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[ba,bb,bc].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
ba.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
bb.frame = CGRect(x: 100, y: 0, width: 100, height: 100)
bc.frame = CGRect(x: 200, y: 0, width: 100, height: 100)
ba.backgroundColor = .blue
bb.backgroundColor = .orange
bc.backgroundColor = .darkGray
ba.addTarget(self, action: #selector(pressa), for: .touchDown)
bb.addTarget(self, action: #selector(pressb), for: .touchDown)
bc.addTarget(self, action: #selector(pressc), for: .touchDown)
}
#objc func pressa(){
ba.layer.borderWidth = 2
}
#objc func pressb(){
bb.layer.borderWidth = 2
}
#objc func pressc(){
bc.layer.borderWidth = 2
}
}
you can add target to all buttons at the forEach and be only one method as #Sh_Khan mention
import UIKit
class ViewController: UIViewController {
var ba = UIButton()
var bb = UIButton()
var bc = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[ba,bb,bc].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.addTarget(self, action: #selector(pressAll(_:)), for: .touchDown)
}
ba.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
bb.frame = CGRect(x: 100, y: 0, width: 100, height: 100)
bc.frame = CGRect(x: 200, y: 0, width: 100, height: 100)
ba.backgroundColor = .blue
bb.backgroundColor = .orange
bc.backgroundColor = .darkGray
}
#objc func pressAll(_ sender:UIButton) {
[ba,bb,bc].forEach { $0.layer.borderWidth = 0 } // reset all
sender.layer.borderWidth = 2
}
}
See how you have used an array in [ba,bb,bc].forEach { ... } to reduce code duplication? Using arrays is the key. Rather than putting the three buttons in an array inline like that, create a property instead:
var buttons: [UIButton]!
override func viewDidLoad() {
super.viewDidLoad()
buttons = [ba,bb,bc]
buttons.forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.addTarget(self, action: #selector(buttonPressed), for: .touchDown)
}
...
}
I have used the same selector buttonPressed for all three buttons. buttonPressed can accept a parameter of type UIButton, that tells us which button is pressed:
#objc func buttonPressed(_ sender: UIButton) {
buttons.forEach { ba.layer.borderWidth = 0 } // deselect all buttons first...
sender.layer.borderWidth = 2 // select the tapped button
}
If you have more than 3 buttons to manage, I suggest you don't use UIButtons at all. You should use a UICollectionView. (Learn how to use them) This view will handle the selection for you. It also allows scrolling when there's not enough space to show all the buttons. You just need to create a custom UICollectionViewCell and override its isSelected property:
override var isSelected: Bool {
didSet {
if isSelected {
self.layer.borderWidth = 2
} else {
self.layer.borderWidth = 0
}
}
}
It could be 1 method like this
[ba,bb,bc].forEach { $0.addTarget(self, action: #selector(pressAll(_:)), for: .touchDown) }
}
#objc func pressAll(_ sender:UIButton) {
[ba,bb,bc].forEach { $0.layer.borderWidth = 0 } // reset all
sender.layer.borderWidth = 2
}

How to add UIImageView to navigation bar in swift?

I have this code that adds a rounded border around a UIImage using UIImageView and I've used UITapGestureRecognizer to let the user tap on the button:
var profilePicture = UIImageView()
func setupUserProfileButton() {
let defaultPicture = UIImage(named: "profilePictureSmall")
profilePicture = UIImageView(image: defaultPicture)
profilePicture.layer.cornerRadius = profilePicture.frame.width / 2
profilePicture.clipsToBounds = true
profilePicture.layer.borderColor = UIColor.black.cgColor
profilePicture.layer.borderWidth = 1
// Letting users click on the image
profilePicture.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(profilePictureTapped))
profilePicture.addGestureRecognizer(tapGesture)
}
How can I add this to the left side of a navigation bar? Is it possible? And I don't think the tap gesture is needed if I can add the ImageView to the navigation bar as a barButtonItem, so you can ignore that. I kinda found some similar questions but they were in objective C and none of what I tried worked.
Here is what I came up with based on an answer:
import UIKit
import Firebase
class CreateStoryPage: BaseAndExtensions {
let userProfileButton = UIButton(type: .custom)
override func viewDidLoad() {
super.viewDidLoad()
// Call all the elements
setupUserProfileButton()
}
// MARK:- Setups
// Setup the user profile button
func setupUserProfileButton() {
userProfileButton.setImage(#imageLiteral(resourceName: "profilePictureSmall.png"), for: .normal)
userProfileButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
userProfileButton.addTarget(self, action: #selector(profilePictureTapped), for: .touchUpInside)
let userProfileView = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
userProfileView.layer.cornerRadius = 14
userProfileView.backgroundColor = .red
userProfileView.addSubview(userProfileButton)
let leftNavBarItem = UIBarButtonItem(customView: userProfileView)
self.navigationItem.setLeftBarButton(leftNavBarItem, animated: true)
}
// if user taps on profile picture
#objc func profilePictureTapped() {
let userProfilePage = UserProfilePage()
present(userProfilePage, animated: true, completion: nil)
}
}
Try this;
private func setupRightItem() {
let userProfileButton = UIButton(type: .custom)
userProfileButton.imageView?.contentMode = .scaleAspectFill
userProfileButton.clipsToBounds = true
userProfileButton.addTarget(self, action: #selector(profilePictureTapped), for: .touchUpInside)
userProfileButton.setImage(#imageLiteral(resourceName: "profilePictureSmall.png"), for: .normal)
userProfileButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: userProfileButton)
userProfileButton.widthAnchor.constraint(equalToConstant: 30).isActive = true
userProfileButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
}
#objc private func goProfile() {
/// -> Action
}
let navBtn = UIButton(type: .custom)
navBtn.setImage("yourImage", for: .normal)
navBtn.frame = CGRect(x: 0, y: 0, width: 28, height: 28)
navBtn.addTarget(self, action: #selector(self.openProfile(_:)), for: .touchUpInside)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 28))
view.cornerRadius = 14
view.backgroundColor = Global.colorBlue
view.addSubview(navBtn)
let leftNavBarItem = UIBarButtonItem(customView: view)
self.navigationItem.setLeftBarButton(leftNavBarItem, animated: true)
#objc
func openProfile(_ sender: UIButton) {
}

Is there any easier way to view UIImageView programmatically?

I have 8 buttons and I want to display a picture every time I press the buttons.
What I wonder is, do I need to have 8 functions to display these images?
Or is there any easier ways?
Here is how I've done it, it works as it should, but I do not want to repeat the same things over and over again?
var imageView1:UIImageView!
var imageView2:UIImageView!
var imageView3:UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
showImage1()
showImage2()
showImage3()
tapGestureRecognizerFunc()
}
#objc func button1Tap() {
if self.imageView1.isHidden {
self.imageView1.isHidden = false
}else{
self.imageView1.isHidden = true
}
}
#objc func button2Tap() {
if self.imageView2.isHidden {
self.imageView2.isHidden = false
}else{
self.imageView2.isHidden = true
}
}
#objc func button3Tap() {
if self.imageView3.isHidden {
self.imageView3.isHidden = false
}else{
self.imageView3.isHidden = true
}
}
func showImage1() {
imageView1 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView1.image = UIImage(named: "Done.png")
imageView1.contentMode = .scaleAspectFit
View1.addSubview(imageView1)
imageView1.isHidden = true
}
func showImage2() {
imageView2 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView2.image = UIImage(named: "Done.png")
imageView2.contentMode = .scaleAspectFit
View2.addSubview(imageView2)
imageView2.isHidden = true
}
func showImage3() {
imageView2 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView2.image = UIImage(named: "Done.png")
imageView2.contentMode = .scaleAspectFit
View3.addSubview(imageView2)
imageView2.isHidden = true
}
func tapGestureRecognizerFunc () {
let exercise1Tap = UITapGestureRecognizer(target: self, action: #selector(button1Tap))
exercise1Tap.numberOfTapsRequired = 2
View1.addGestureRecognizer(exercise1Tap)
let exercise2Tap = UITapGestureRecognizer(target: self, action: #selector(button2Tap))
exercise2Tap.numberOfTapsRequired = 2
View2.addGestureRecognizer(exercise2Tap)
let exercise3Tap = UITapGestureRecognizer(target: self, action: #selector(button3Tap))
exercise3Tap.numberOfTapsRequired = 2
View3.addGestureRecognizer(exercise3Tap)
}
yes i'm newbie
Since I don't know, where and how you create the Buttons it is difficult to answer.
The following is just a tip.
You should use an array of UIImageView
Your callback should use the Form buttonAction(sender : UIButton)
You could use a tag for the button to get the number of the corresponding button
For example:
class ViewController: UIViewController {
var imageviews : [UIImageView] = []
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...8 {
let imageview = UIImageView()
view.addSubview(imageview)
imageview.tag = i
imageviews.append(imageview)
let button = UIButton(frame: CGRect(x: 0, y: CGFloat(i)*50.0, width: 100, height: 30))
view.addSubview(button)
button.setTitle("Button \(i)", for: .normal)
button.setTitleColor(.black, for: .normal)
button.tag = i
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
}
}
#objc func buttonAction(sender : UIButton) {
let index = sender.tag
print("Button \(index) pressed")
imageviews[index].isHidden = !imageviews[index].isHidden
}
}

Present viewController after touchUp GIDSignInButton()!

I make a Google Auth for my App, but I don't know how to present a new viewController after touchup GIDSignInButton!
Here how I make GIDSignInButton:
viewDidLoad (){
let googleBtn = GIDSignInButton()
googleBtn.frame = CGRect(x: 16, y: 500 + 66, width: view.frame.width - 32, height: 35)
view.addSubview(googleBtn)}
Here's a code example that will present a second, programmatically generated view controller using a standard UIButton. Obviously, you could do the same with your GIDSignInButton:
class MyViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
let button = UIButton(frame: CGRect(x: 10, y: 250, width: self.view.frame.width - 20, height: 35))
button.setTitle("Go to VC2", for: .normal)
button.backgroundColor = UIColor.blue
button.addTarget(self, action:#selector(self.buttonClicked), for: .touchUpInside)
self.view.addSubview(button)
}
func buttonClicked(sender: UIButton!)
{
let secondViewController = MySecondViewController()
present(secondViewController, animated: true, completion: {})
}
}
class MySecondViewController:UIViewController
{
override func viewDidLoad() {
self.view.backgroundColor = UIColor.darkGray
}
}
Note, however, that if you are presenting multiple views, you are advised to embed them in a Navigation Controller, as per Apple's Documentation