Hi,
creating a second part of the tutorial as some folks wanted to do this trick with a few variations.
( link to part I )
As a start a Navigation controller got involved π
So you end up with a problem where buttons would disappear as you go back and forth.
Solution for this is posted at the end of part 1.
However there was someone who wanted to have different main button and the later created buttons.
Here is a solution to that.
First of all embed your project in a Navigation Controller, so you end up with something like that :
Then, change your project(ViewController.swift) to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
import UIKit var arrayOfVillains = ["MAIN BUTTON"] var arrayOfNewButtons = [String]() class ViewController: UIViewController { var number: Int = 1 var buttonY: CGFloat = 80 // our Starting Offset, could be 0 override func viewDidLoad() { super.viewDidLoad() addStartingButtons() displayNewButtons() } func addStartingButtons() { for villain in arrayOfVillains { let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30)) buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding villainButton.backgroundColor = UIColor.darkGrayColor() villainButton.setTitle("name: \(villain)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here. villainButton.titleLabel?.text = "\(villain)" villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added } } func addNewButton() { let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30)) buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding villainButton.backgroundColor = UIColor.blueColor() villainButton.setTitle("New Button : \(number)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here. villainButton.titleLabel?.text = "\(number)" villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added arrayOfNewButtons.append("New Button : \(number)") } func displayNewButtons() { for villain in arrayOfNewButtons { let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30)) buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding villainButton.backgroundColor = UIColor.blueColor() villainButton.setTitle("New Button: \(number)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here. villainButton.titleLabel?.text = "\(villain)" villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added number++ } } func villainButtonPressed(sender:UIButton!) { if sender.titleLabel?.text != nil { println("You have chosen Villain: \(sender.titleLabel?.text)") addNewButton() number++ } else { println("Nowhere to go :/") } } } |
Then, once you run the project, you should see this:
Once you add some buttons:
Now, if you go back and forth the buttons should still be there.
I was actually gonna add another example on how to just add the buttons to a new UIView and
just add it later, however I found some problems with doing that and a navigation controller, so that is probably the best way of doing it ( at least for now π )
Cheers !
I have another question, how do we layout the buttons in rows of 2,in terms of after 2 buttons it will automatically create the 3rd button on the second row, within the GUI size?Since my buttons are of circle type. You have been so much of a great help!!! Cheers mate π
@bleeary_d:disqus reply above
Oh, well if you want to have 2 per row you would have to add a variable for the X offset as well.
Then create flags( Bool ) that will check to see where we are at.
Something like:
var secondColumn: Bool = false
var buttonY: Int = 20
var buttonX: Int = 50
then you will do something like this in your button create logic:
let villainButton = UIButton(frame: CGRect(x: buttonX, y: buttonY, width: 250, height: 30))
if secondColumn == true {
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart, if next button is on the next row only
buttonX = buttonX – 50 // go back to column 1 if this is column 2
secondColumn = false
} else {
buttonX = buttonX + 50
secondColumn = true
}
Something like that, but I just typed it, haven’t actually ran it π
Hey, just an update, your code works! You are really a lifesaver and thanks so much for all the help π
Glad that worked for you! Good luck !
Hi! I hope I am not troubling you but there’s another problem that I faced π‘ I currently have dynamic butttons created every time the add new button is pressed, and all the dynamic buttons leads to the same view. The problem is I couldn’t display the individual button’s data when the button is selected. For e.g button 1 ‘s data when button 1 is selected and button 3 ‘s data when button 3 is selected and so on. Instead, it only shows the latest data inputted, which is then displayed on all the buttons… Thanks in advance! π ( Data are retrieved from external SQLite database)
Yeah, the problem is that in this method you were only using the String as the button name. Like I said in theory there is a better way, so you can either make the whole View a global variable ( that ends up being buggy, due to the UIButtons linking ) or I guess you can saving each button in an array instead. So instead of the String Array you will use an Array of [UIButton]. I have the feeling that this might not work as well π
The other solution is to use another Array with the Buttons info in parallel ( or use a dictionary )
So you can create a second Array for the Labels for example: var arrayOfNewButtonsLabels = [String]()
And then when you create a new button you can append to it as well with the label.
Then when you create the new buttons you will get the button Title and Label from the stored variables.
It really depends on what exactly you want to do with it.