How to create Custom Toast UIView with Button using Swift? - ios

In my case, I am trying to create toast message popup with custom UI design like below sample image. It should be common class with button actions and it should allow to call from other ViewControllers with some message and time interval passing parameters. I am looking some initiation codebase with .XIB. Please help me to achieve this.
Expected Toast UI

It is not tested but it might help you
func showToast(message : String) {
// add label
let toastLabel = UILabel(frame: CGRect(x: 30, y: self.view.frame.size.height-150, width: 330, height: 35))
toastLabel.text = message
toastLabel.alpha = 1.0
toastLabel.layer.cornerRadius = 10;
toastLabel.clipsToBounds = true
//add button
let button = UIButton.init(type: .custom)
button.frame = CGRect.init(x: toastLabel.frame.width - 50, y: toastLabel.frame.origin.y + 20, width: 40, height: 40)
self.view.addSubview(toastLabel)
self.view.addSubview(button)
UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: {
toastLabel.alpha = 0.0
}, completion: {(isCompleted) in
toastLabel.removeFromSuperview()
})
}

Related

Why my UILabel doesn't conforms to the inital frame?

I'm trying to create a popup label over the imageview. But in my application it doesn't work. I've made a test application with the same screen: UIImageView and below a UIView with a UIButton on the view.
So, where are two questions.
What could be difference in a code for such a different behaviour?
Why in my application the UILabel doesn't conforms to the initial frame?
The code of the function inside my viewController is the same:
private func showBanner(startY: CGFloat, targetView: UIView) {
let height: CGFloat = 42
let finishY = startY - height
let bannerLabel = UILabel(frame: CGRect(x: 0, y: startY, width: self.view.frame.width, height: height))
bannerLabel.translatesAutoresizingMaskIntoConstraints = false
bannerLabel.font = UIFont.systemFont(ofSize: 13, weight: .regular)
bannerLabel.textColor = .lightGray
bannerLabel.backgroundColor = .black
bannerLabel.textAlignment = .center
bannerLabel.numberOfLines = 1
bannerLabel.text = "You've added the item to the favorites"
targetView.addSubview(bannerLabel)
UIView.animate(withDuration: 0.5, animations: {
bannerLabel.frame = CGRect(x: 0,
y: finishY,
width: self.view.frame.width,
height: height
)
}) {
_ in
UIView.animate(withDuration: 0.5, delay: 1.0, options: .curveLinear, animations: {
bannerLabel.frame = CGRect(x: 0,
y: startY,
width: self.view.frame.width,
height: height
)
}, completion: {
_ in
bannerLabel.removeFromSuperview()
})
}
}
The function is being called so:
showBanner(startY: itemsImageView.frame.maxY, targetView: itemsImageView)
The problem was in the line:
bannerLabel.translatesAutoresizingMaskIntoConstraints = false
As soon as this line was removed, the problem has dissapeared.

Cannot animate UIImageview

My issue is that when I press the button that runs the dealToPlayer function(), everything acts as if a card has been dealt, updates total value of cards dealt, but it does not show any animation of the card being dealt or placed. Why might this be? I am not using auto layout for this scene at all.
func dealToPlayer() {
let index = Int(arc4random_uniform(UInt32(deckCards.count)))
let drawnCard = deckCards.remove(at: index)
randomCards.append(drawnCard)
randomCard = randomCards[3 + cardSelect]
image = UIImageView(frame: CGRect(x: self.deckLocation.x, y: self.deckLocation.y, width: self.width, height: self.height))
image.image = mapping[randomCard]
cardsOut = cardsOut + 1
print("cards out is currently: \(cardsOut)")
cardSelect = cardSelect + 1
UIView.animate(withDuration: 0.5, delay: 1.5, options: [], animations: {
self.image.frame = CGRect(x: self.cardTwoLocation.x - (self.cardsOut * self.thirdWidth), y: self.cardTwoLocation.y, width: self.width, height: self.height)
}, completion: nil)
checkPlayerValue()
}
First, make sure your image view is added to your view controller.
Second, make sure your animation is called by putting a break point.
Third, print out the location and make sure the new x and y are valid, and they are different than the previous x and y.
Here is a sample duplicate of your code an it works fine
image = UIImageView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
image.backgroundColor = .red
self.view.addSubview(image)
UIView.animate(withDuration: 0.5, delay: 1.5, options: [], animations: {
self.image.frame = CGRect(x: 200, y: 200, width: 100, height: 100)
}, completion: nil)

Repeat while loop doesn't work - why?

I want an imageView in my viewController to "pulsate", that means become bigger and then tinier again and repeat that until the "start"-button was pressed. The problem is, that every time I call that function in the viewDidLoad() with a repeat-while-loop, it has got a breakpoint for whatever reason.
That's the part of my viewDidLoad():
repeat {
pulsate()
} while hasStarted == false
When I press the start button, hasStarted becomes true and it should stop pulsating. But it doesn't even start the function, it immediately calls an error. Where's the problem?
Here's my pulsate()-function
func pulsate()
{
frameOR = imageView.frame
frameNext = CGRect(x: imageView.frame.midX - 35, y: imageView.frame.midY - 35, width: 80, height: 80)
let frameVDL = CGRect(x: imageView.frame.midX - 150, y: imageView.frame.midY - 150, width: 300, height: 300)
if start == false
{
UIView.animate(withDuration: 2, animations: {
self.imageView.frame = frameVDL
}) { (finished) in
UIView.animate(withDuration: 2, animations: {
self.imageView.frame = self.frameOR
}, completion: nil)
}
}
}
Thank your for your help! Have a great day!
You can use UIView.animate's built-in options to really simplify what you're trying to do, and avoid locking up the thread.
Give this a try:
let frameOR = imageView.frame
let frameVDL = CGRect(x: imageView.frame.midX - 150, y: imageView.frame.midY - 150, width: 300, height: 300)
UIView.animate(withDuration: 2.0,
delay: 0.0,
options: [UIViewAnimationOptions.autoreverse, UIViewAnimationOptions.repeat],
animations: {
imageView.frame = frameVDL
},
completion: nil)
Your imageView should now be in a full "pulsing" loop, without needing any additional code. When you're ready to stop the animation, just call:
imageView.layer.removeAllAnimations()

How to animate UIButton frame from left to right and reverse

My current method is to add a view to the button as subview:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 0, height: 60))
button.setTitle("Add", for: .normal)
buttonView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 60))
buttonView.backgroundColor = .black
button.addSubview(buttonView)
And then animate the width of the view:
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseIn, animations: {
self.buttonView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 60)
}, completion: nil)
What I don't like about this is that the button title remains static. I want it to be part of the animation.
I also try to animate the frame of the button instead, but it doesn't seem to work. Nothing happens.
My button is added to the UITextField inputAccessoryView so I am not sure if this is the problem.
Any suggestions how can I animate the button correctly ?
You don't need an additional subview for UIButton in order to animate it's frame.
Try to add layoutIfNeeded() before animation and inside animation closure:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
button.setTitle("Add", for: .normal)
button.setTitleColor(UIColor.green, for: .normal)
button.backgroundColor = UIColor.black
view.addSubview(button)
button.layoutIfNeeded()
UIView.animate(withDuration: 3, delay: 0.0, options: .curveEaseIn, animations: {
button.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 60)
button.layoutIfNeeded()
}, completion: nil)
Hope this helps.

How to position one image in front of another?

I'm new in Swift development, so I hope you guys can help.
I have a game map, it contains 50 different ImageView (position) from 1 to 50, 4 characters, and a dice roll(button).
When I press i dice roll button it returns a random number between 1 to 6.
For example: I pressed dice roll button and it returned 4, so now i want to move my character to new position(to ImageView place4).
Here is my code:
var girl: UIImageView!
var place4 = UIImageView(image: UIImage(named: "4.png"))
girl.frame = CGRect(x: 200, y: 200, width: 45, height: 100)
scrollView.addSubview(girl)
place4.frame = CGRect(x: 210, y: 145, width: 60, height: 30)
scrollView.addSubview(place4)
func moveCharacter(sender:UIButton!) {
let duration = 1.0
let delay = 0.0 // delay will be 0.0 seconds (e.g. nothing)
let options = UIViewAnimationOptions.CurveEaseInOut // change the timing curve to `ease-in ease-out`
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
// any changes entered in this block will be animated
self.girl.center = CGPointMake(self.place4.center.x, self.place4.center.y - 30)
}, completion: { finished in
// any code entered here will be applied
// once the animation has completed
//self.place4.hidden = true
})
}
When I press button, UIImageView "girl" should move to X and Y coordinate of UIImageView "place4". To move character to new position I use following code:
self.girl.center = CGPointMake(self.place4.center.x, self.place4.center.y - 30)
and girl image should appear over place4 image, but actually girl image appear behind place4 image, pls look at the screenshot:
But actually what i try to achieve is this:
I tried to use UiView methods bringSubviewToFront and sendSubviewToBack, but it did'n help.
How can I fix this issue? Or maybe you guys can advise me better solution?
Thanks to all in advance.
Add girl after you add place4 image view.
scrollView.addSubview(place4)
Result should be like this:
girl.frame = CGRect(x: 200, y: 200, width: 45, height: 100)
place4.frame = CGRect(x: 210, y: 145, width: 60, height: 30)
scrollView.addSubview(place4)
scrollView.addSubview(girl)
Try this one ....
var girl: UIImageView!
var place4 = UIImageView(image: UIImage(named: "4.png"))
place4.frame = CGRect(x: 210, y: 145, width: 60, height: 30)
scrollView.addSubview(place4)
girl.frame = CGRect(x: 200, y: 200, width: 45, height: 100)
scrollView.addSubview(girl)
func moveCharacter(sender:UIButton!) {
let duration = 1.0
let delay = 0.0 // delay will be 0.0 seconds (e.g. nothing)
let options = UIViewAnimationOptions.CurveEaseInOut // change the timing curve to `ease-in ease-out`
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
// any changes entered in this block will be animated
self.girl.center = CGPointMake(self.place4.center.x, self.place4.center.y - 30)
}, completion: { finished in
// any code entered here will be applied
// once the animation has completed
//self.place4.hidden = true
})
}

Resources