I am a beginner in Xcode. I am trying to make an app which displays confetti on a button click. However, when I press the button, the confetti is displayed but it never stops. It blocks the buttons and the view. I am using a Cocoapod - SAConfettiView.
This code in on Xcode 10. I believe that the Confetti blocks the main view. I use playConfetti as IBaction function.
#IBAction func playConfetti(_ sender: UIButton, forEvent event: SAConfettiView) {
let confettiView = SAConfettiView(frame: self.view.bounds)
confettiView.intensity = 1
confettiView.type = .Star
confettiView.startConfetti()
view.addSubview(confettiView)
}
Do I have to use the If-Else statement?
Thank you!
Updated Answer
To stop the SAConfettiView call the function,
confettiView.stopConfetti()
Change your Button Action code to the following:
let confettiView = SAConfettiView()
#IBAction func startClicked(_ sender: Any)
if confettiView.isActive() {
confettiView.stopConfetti()
confettiView.removeFromSuperview()
}
else{
confettiView = SAConfettiView(frame: self.view.bounds)
confettiView.intensity = 1
confettiView.type = .Star
confettiView.startConfetti()
view.addSubview(confettiView)
self.view.bringSubviewToFront(sender as! UIButton)
}
}
Related
Essentially I want a label to appear as a subview when I add it and not wait until the current thread has finished what it is doing. In the below example, the label appears in the UI of the app at the same time 'Awake' is printed. Do you know how I can get the subview to appear in the UI before the thread sleeps?
#IBAction func ButtonTapped(_ sender: Any) {
let label = UILabel(frame: self.view.bounds)
label.text = "Label Text"
self.view.addSubview(label) // I want this to appear on the UI before...
sleep(3)
print("Awake") // ... this is printed
}
And enclosing the addSubView() line within DispatchQueue.main.async {} doesn't fix the issue.
Thanks.
Thanks to Paulw11, I figured out that I need to do the processing on a background thread. Simple solution in swift:
#IBAction func ButtonTapped(_ sender: Any) {
let label = UILabel(frame: self.view.bounds)
label.text = "Label Text"
self.view.addSubview(label) // I want this to appear on the UI before...
DispatchQueue.global(qos: .background).async {
sleep(3)
print("Awake") // ... this is printed
}
}
As the code shows, I have the switch which starts the animation when turned on, but the confetti anyway is displayed and doesn't let me have button interactions !
#IBAction func `switch`(_ sender: UISwitch) {
if(sender.isOn==true){
senderText.text="YAYA!"
supportText.text="we have added a reminder for you"
supportIcon.isHidden=false
support2.isHidden=true
confettiView.startConfetti()
}
else{
senderText.text="OKAY"
supportText.text="you wont be disturbed"
supportIcon.isHidden=true
support2.isHidden=false
}
}
var confettiView: SAConfettiView!
override func viewDidLoad() {
super.viewDidLoad()
confettiView = SAConfettiView(frame: self.view.bounds)
confettiView.colors = [UIColor(red:0.95, green:0.40, blue:0.27, alpha:1.0),
UIColor(red:1.00, green:0.78, blue:0.36, alpha:1.0),
UIColor(red:0.48, green:0.78, blue:0.64, alpha:1.0),
UIColor(red:0.30, green:0.76, blue:0.85, alpha:1.0),
UIColor(red:0.58, green:0.39, blue:0.55, alpha:1.0)]
confettiView.intensity = 0.5
confettiView.type = .Diamond
confettiView.type = .Confetti
view.addSubview(confettiView)
What is happening is that your confettiView is on top of all the other views and is receiving all the touches, preventing buttons and switches to receive them
confettiView.isUserInteractionEnabled = false
This line of code to be inserted right after your confettiView initialization should solve the issue, as the confetti view will no longer intercept all touches.
Another solution (depending on your design requirements) would be to bring all the buttons to front, if you have a reference for them, or to remove the confetti view if you want an animation of defined duration.
Also please not that
confettiView.type = .Diamond
confettiView.type = .Confetti
will cause the type to be .Confetti. Consider to remove one of the two type assign statement. :)
Your confettiView is above all of your other UIView's and UIButton's.
confettiView = SAConfettiView(frame: self.view.bounds) makes your confettiView the size of the entire screen. You're then adding it to the view with view.addSubview(confettiView). Remove the confettiView after your animation.
For example:
confettiView.removeFromSuperview()
I'm new to Swift and I assume this is a fundamental question to programming for iOS.
I have three buttons in my storyboard and I want to customize how those buttons look if pressed once, twice and three times.
I also have three themes (pink, blue and orange). What I thought of doing is to create three new classes called pink,blue and orange.swift
I don't want to create them programmatically, only style them programmatically.
What I lack to understand is how do I call the function (Example: "ButtonIsPressed") from my pink.swift class into my #IBAction and #IBOutlet in the main view controller that is also object oriented (ie. I don't want to create a function for every button)?
I can't really find a decent and up-to-date Swift 3 Tutorial for this, any help or advice on this topic will be greatly appreciated.
Why can it not be as simple as?:
#IBAction func buttonPressed(_ sender: UIButton!) {
self.backgroundColor = myPinkCGolor
}
I think shallowThought's answer will work for changing backgroundColor based on button state of a specifically named IBOutlet.
I have three buttons in my storyboard and I want to customize how those buttons look if pressed once, twice and three times.
If you want to maintain "state", as in have a "counter" for how many times a button's been clicked or tapped, you can use the "tag" property of the button. Set it to zero, and in your IBAction functions increment it. (Like shallowThought said, use .touchUpInside and .touchDown for the events.)
Also, you have one minor - but important! - thing wrong in your code Brewski:
#IBAction func buttonPressed(_ sender: UIButton!) {
self.backgroundColor = myPinkCGolor
}
Should be:
#IBAction func buttonPressed(_ sender: UIButton!) {
sender.backgroundColor = myPinkCGolor
}
So combining everything - up vote to shallowThought (also, changing his AnyObject to UIButton and making it Swift 3.x syntax on the UIColors - and would end up with this. Note that there is no need for an IBOutlet, and you can wire everything up in IB without subclassing:
// .touchUpInside event
// can be adapted to show different color if you want, but is coded to always show white color
#IBAction func buttonClicked(sender: UIButton) {
sender.backgroundColor = UIColor.whiteColor()
}
// .touchDown event
// will show a different color based on tap counter
#IBAction func buttonReleased(sender: UIButton) {
switch sender.tag {
case 1:
sender.backgroundColor = UIColor.blue
case 2:
sender.backgroundColor = UIColor.red
case 3:
sender.backgroundColor = UIColor.green
default:
sender.backgroundColor = UIColor.yellow
}
sender.tag += 1
}
There is no methode to set the backgroundColor for a certain state, like there is for other UIButton properties, so you have to listen to the buttons actions:
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBAction func buttonClicked(sender: AnyObject) { //Touch Up Inside action
button.backgroundColor = UIColor.whiteColor()
}
#IBAction func buttonReleased(sender: AnyObject) { //Touch Down action
button.backgroundColor = UIColor.blueColor()
}
...
}
or set a unicolor image withimage:UIImage, forState:.selected.
Ive been looking around for methods to change active state on Button click. I have 4 buttons when clicked the reposition my scroll view as programmed.
I am trying to set the background color to fade a bit if clicked. Im able to set the background color but it stays the same faded color when another is clicked. It doesnt return to an inactive state.
Any simple way to acheive this onckick button behavior globally?
heres my button click func's:
#IBAction func tab1(sender: UIButton)
{
slScrollView.setContentOffset(CGPointMake(0.0, 0.0), animated: true)
tab1.backgroundColor = UIColor.grayColor()
tab2.selected = false
tab3.selected = false
}
#IBAction func tab2(sender: UIButton)
{
slScrollView.setContentOffset(CGPointMake(0.0, 650.0), animated: true)
tab2.backgroundColor = UIColor.grayColor()
tab1.selected = false
tab3.selected = false
}
#IBAction func tab3(sender: UIButton) {
slScrollView.setContentOffset(CGPointMake(0.0, 1370.0), animated: true)
tab3.backgroundColor = UIColor.grayColor()
tab1.selected = false
tab2.selected = false
}
First, create an IBOutletCollection (or four separate outlets) to the buttons. Then create an IBAction method and set all four buttons to fire it when tapped. In the method, do the background fade animation on the button that fired the action (which is passed into the handler as its sender argument, then reset the states of the other outlet buttons.
The way I would code it:
// Outlet to all of the buttons. ctrl+drag each button to this outlet.
#IBOutletCollection buttons = [UIButton]()
// Set *all* of the buttons to fire this method.
#IBAction func buttonTapped(sender: AnyObject!) {
(sender as? UIButton).backgroundColor = <whatever>
for button in buttons.filter({ $0 != sender }) {
button.backgroundColor = <default>
}
}
I've created an IBAction from a button on the storyboard. After it is clicked, I want to disable it so its no longer functional. How can I do this?
#IBAction func b1(sender: AnyObject) {
displayLabel(1)
}
Create an outlet for your button and set its enabled property to false in your b1 func. Say your outlet is "button1":
button1.enabled = false
#Mike Taverne is right about disabling button. But from the line
button.enabled = false
will make button dark greyed out. And user clearly see that it is not tappable or clickable.
But if we use this line:
button.userInteractionEnabled = false
Then button UI will not change and user thinks that it is tappable. But related action event will not called.
In both case action will not called but the look of button will matter here.
Code will suppose to be like:
#IBAction func b1(sender: AnyObject) {
var view = UIView()
view = sender as UIView
view.userInteractionEnabled = false
}
You will get the button instance in that function as sender (AnyObject).
You need to convert it to UIButton and set it's userInteractionEnabled or enabled property to false.
#IBAction func b1(sender: AnyObject)
{
displayLabel(1)
var button = sender as UIButton;
button.userInteractionEnabled = false;
}
Alternatively, you can do it using:
#IBAction func b1(sender: UIButton)
{
displayLabel(1)
sender.enabled = false;
}