Fade Animation for UIImages in Swift - ios

I have a set of images that i would like to have fade in the background of my login screen. I cant find anything in swift that can do this. Is there a way that i would be able to?
Heres my current code:
override func viewDidLoad() {
super.viewDidLoad()
startAnimating()
// Do any additional setup after loading the view, typically from a nib.
}
func startAnimating(){
backgroundImage.animationImages = [
UIImage(named: "background1.jpg"),
UIImage(named: "background2.jpg")
]
backgroundImage.animationDuration = 3
backgroundImage.startAnimating()
}

The below code will help you to animate image with fadeOut effect and change the background.
import UIKit
class ViewController: UIViewController {
var imgView:UIImageView? //class variable to display you bg image
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
imgView = UIImageView(frame: self.view.frame) //imgView to display background
self.view.insertSubview(imgView, atIndex: 0) //imgview add above the background of main view
animateImage(1) /*call animageImage with parameter number as image number as i user image name as avatar1.png, avatar2.png, avatar3.png and avatar4.png*/
}
func animateImage(no:Int)
{
var imgNumber:Int = no
let t:NSTimeInterval = 1;
let t1:NSTimeInterval = 0;
var name:String = "avatar\(imgNumber).png"
imgView!.alpha = 0.4
imgView!.image = UIImage(named:name);
//code to animate bg with delay 2 and after completion it recursively calling animateImage method
UIView.animateWithDuration(2.0, delay: 0, options:UIViewAnimationOptions.CurveEaseOut, animations: {() in
self.imgView!.alpha = 1.0;
},
completion: {(Bool) in
imgNumber++;
if imgNumber>4 //only for 4 image
{
imgNumber = 1
}
self.animateImage(imgNumber);
})
}
}

Related

Making a UIView update behind another one in the same view controller

I'm working in swift to make an app the uses the cocoapod framework BBSlideoutMenu to display a menu. I am also using the cocoapod framework ChameleonFramework. What I'm trying to do is make the hamburger button that I'm using change colour when it is opened. I haven't yet implemented it, but I also want to make the bar on top transparent. I've recorded it here so you can see what is happening. Basically, the view only gets updated when I slide away the menu.
Disclaimer: I am aware that using a hamburger menu is viewed as bad code design, unfortunately it is what I need in this app.
Here is my code:
import UIKit
import BBSlideoutMenu
import ChameleonFramework
class ViewController: UIViewController, BBSlideoutMenuDelegate {
#IBOutlet var slideMenu: BBSlideoutMenu!
var button: HamburgerButton! = nil
var menuOpen = false;
let screenSize: CGRect = UIScreen.mainScreen().bounds
let topBar = UIView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height * 0.1))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
view.backgroundColor = UIColor.whiteColor()
topBar.backgroundColor = FlatRed()
button = HamburgerButton(frame: CGRectMake(0, 20, 54, 54))
button.addTarget(self, action: #selector(toggleMenu(_:)), forControlEvents:.TouchUpInside)
topBar.addSubview(button)
view.addSubview(topBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
slideMenu.setupEdgePan()
slideMenu.slideDirection = .Right
slideMenu.shrinkAmount = 0
slideMenu.slideTravelPercent = 0.87
slideMenu.menuOffset = 0
slideMenu.zoomFactor = 1
slideMenu.springEnabled = false
slideMenu.backgroundColor = FlatRed()
slideMenu.delegate = self
slideMenu.setupEdgePan()
}
func toggleMenu(sender : HamburgerButton!) {
if(menuOpen) {
slideMenu.dismissSlideMenu(animated: true, time: nil)
} else {
slideMenu.presentSlideMenu(true) { () -> Void in
//Runs after menu is presented
}
}
}
func didPresentBBSlideoutMenu(menu: BBSlideoutMenu) {
menuOpen = true
button.changeColor(UIColor.blackColor())
}
func didDismissBBSlideoutMenu(menu: BBSlideoutMenu) {
menuOpen = false
button.changeColor(UIColor.whiteColor())
}
}
I am using this hamburger menu button, which has been created with CoreGraphics and QuartzCore, and have added the following function for change colour.
func changeColor(color: UIColor) {
for layer in [ self.topStroke, self.middleStroke, self.bottomStroke ] {
layer.fillColor = nil
layer.strokeColor = color.CGColor
layer.lineWidth = 4
layer.miterLimit = 4
layer.lineCap = kCALineCapRound
layer.masksToBounds = true
let strokingPath = CGPathCreateCopyByStrokingPath(layer.path, nil, 4, .Round, .Miter, 4)
layer.bounds = CGPathGetPathBoundingBox(strokingPath)
layer.actions = [
"strokeStart": NSNull(),
"strokeEnd": NSNull(),
"transform": NSNull()
]
self.layer.addSublayer(layer)
}
}
Edit: I have tried using setNeedsDisplay on the button, the topBar, and both of them consecutively in the functions toggleMenu, didPresentBBSlideoutMenu and didDismissBBSlideoutMenu and it didn't work
I have also tried calling it on the actual view (self.view)
Try calling setNeedsDisplay the button.

FBNativeAdView is not presented - Swift

I am trying to present Facebook Native Ad Template with no luck.
class ViewController: UIViewController, FBNativeAdDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
facebookAdViewContainer.backgroundColor = UIColor.greenColor()
let nativeAd = FBNativeAd(placementID: <id>)
nativeAd.delegate = self
nativeAd.loadAd()
...
}
func nativeAdDidLoad(nativeAd: FBNativeAd)
{
let attributes = FBNativeAdViewAttributes()
attributes.backgroundColor = UIColor.blueColor()
let adview = FBNativeAdView(nativeAd: nativeAd, withType:FBNativeAdViewType.GenericHeight300)//, withAttributes: attributes)
adview.hidden = false
self.topBannerViewContainer.addSubview(adview)
}
...
}
As you can see in the picture, the ad is not showing. At least I would expect to see blue background of the ad, but all I can see is the green background of the container

Button click crashes the whole application

I am currently building an application's UI without using IB or storyboard. I have the following hierarchy:
1. ViewController: which is the main view controller.
2. DrawerViewController: which is the view controller for the lower drawer menu.
The main view controller adds as a subview the drawerViewController's view.
3. Add Button: this is a UIButton created and added programatically to the drawerViewController's view.
The problem is if I clicked on the add button, the application crashes, giving absolutely no error messages in the output, except (lldb).
I have tried the following:
Change the selector name and the method name.
Checked the name of the selector method.
Added and removed the parameter of the selector method.
Changed the name of the button.
Added the button inside another view.
There's no way to trace the bug using breakpoints, because the application is compiling just fine, and the app crashes only if you click on the button.
Here's a link to a testing project I created to show the problem:
GitHub
ViewController:
class ViewController: UIViewController //, DrawerDelegate
{
//Lower Drawer.
var drawerView: DrawerView!
var drawerViewHidden: Bool = false
var addButton: UIButton!
var viewHeight: CGFloat! = 0
var viewWidth : CGFloat! = 0
var shownDrawerViewY: CGFloat!
var hiddenDrawerViewY: CGFloat!
init()
{
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Setup UI
setUpUI()
}
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK:- UI initialization.
/**
Private function that setsup the UI.
*/
private func setUpUI()
{
setUpDrawer()
}
//MARK: Drawer setup.
/**
A private function that programatically creataes a drawer and add it to the view.
*/
private func setUpDrawer()
{
var controller = DrawerViewController(width: self.view.frame.width, height: self.view.frame.height)
self.view.addSubview(controller.view)
//Hide
// toggleDrawer()
}
//MARK:- Delegates.
//MARK: DrawerDelegate methods.
func addButtonClicked(sender: UIButton)
{
// toggleDrawer()
}
}
DrawerViewController
class DrawerViewController: UIViewController
{
//Drawer variables.
var drawerViewHidden: Bool = false
var addPinDrawer: AddPinDrawer!
var viewHeight: CGFloat! = 0
var viewWidth : CGFloat! = 0
var shownDrawerViewY: CGFloat?
var hiddenDrawerViewY: CGFloat?
var addButton: UIButton?
init(width: CGFloat, height: CGFloat)
{
super.init(nibName: nil, bundle: nil)
viewWidth = width
viewHeight = height
setUpUI()
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
required override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
{
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
//MARK:- UI setup
func setUpUI()
{
setUpDimensions()
setUpDrawerElements()
// toggleDrawer()
}
func setUpDimensions()
{
//Determine the y in the case drawer is shown
shownDrawerViewY = viewHeight * 2.0/8.0
//Determine the height of the drawer.
let drawerHeight = viewHeight * 6.0/8.0
//Determine the y in the case drawer is hidden
hiddenDrawerViewY = viewHeight * 7.4/8.0
//Create the frame, starting with the drawer shown.
let frame = CGRectMake(0, shownDrawerViewY!, viewWidth, drawerHeight)
//Create a new Drawer View.
self.view = UIView(frame: frame)
setUpAddButton(frame)
//Setup the background image of the drawer.
self.view.backgroundColor = UIColor(patternImage: UIImage(named: Constants.drawerBackgroundImage)!)
}
func setUpDrawerElements()
{
//Setup the button.
setUpAddPinDrawer()
}
func setUpAddPinDrawer()
{
addPinDrawer = AddPinDrawer(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
// self.view.addSubview(addPinDrawer)
}
//MARK: Handling drawer toggles
func toggleDrawer()
{
//Toggle the variable.
drawerViewHidden = !drawerViewHidden
//If the drawer must be hidden.
if drawerViewHidden
{
hideDrawer()
}
//If the drawer must be shown
else
{
showDrawer()
}
}
func hideDrawer()
{
//Hide the drawer
UIView.animateWithDuration(0.6, animations: { () -> Void in
self.view.frame.origin.y = self.hiddenDrawerViewY!
})
// drawerView.hideDrawer()
}
func showDrawer()
{
UIView.animateWithDuration(0.6, animations: { () -> Void in
self.view.frame.origin.y = self.shownDrawerViewY!
})
// drawerView.showDrawer()
}
func setUpAddButton(frame: CGRect!)
{
//Determine the button dimensions.
let width:CGFloat = 75.0//1.0/10.0 * viewHeight
let x = frame.width/2.0 - width/2.0
//Button background image.
let background = UIImage(named: Constants.addButtonBackgroundImage)!
//Create the button.
addButton = UIButton(frame: CGRectMake(x, -width/2.0, width, width)) as UIButton
// addButton!.setImage(background, forState: UIControlState.Normal)
addButton?.backgroundColor = UIColor.yellowColor()
//Add the event handler.
addButton!.addTarget(self, action: "buttonAdd:", forControlEvents: .TouchUpInside)
//Set it rotated.
// self.addButton!.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_4))
//Add the button to the subview.
self.view.addSubview(addButton!)
// println(addButton!.targetForAction("test", withSender: addButton)!)
}
func buttonAdd(sender: UIButton)
{
println("Helloooo asdf")
}
}
I have solved the problem. There's a very little mistake in the initiation of the DrawerViewController, In the main view controller, I am creating a variable called DrawerViewController and initiating its view. This variable will be deallocated once the method is done, which means all events will not be handled. Causing the app to crash since there's no method to handle the button's events.
The solution:
Make the DrawerViewController an instance variable and initialise it in the main view controller.

button.setTitle blanks out image view

Can anyone tell me why setting the button.setTitle(string, forState) function blanks out the UIImage?
If I comment out both lines that use the button.setTitle, the animation runs fine. When the lines are there, the animation disappears when I press the button.
The var cryButton: UIButton and the function UpdateImage refer to the same button, but I tried adding a second button and referencing the title in that, and it had the same effect. It blanks out the image.
I'm stumped :)
import UIKit
class ViewController: UIViewController {
var counter = 1
var numImages = 8
var toggle = true
var timer = NSTimer()
#IBOutlet weak var babyImage: UIImageView!
#IBOutlet weak var cryButton: UIButton!
#IBAction func UpdateImage(sender: AnyObject) {
if toggle == true {
timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("doanimation"), userInfo: nil, repeats: true)
cryButton.setTitle("Stop crying", forState: UIControlState.Normal)
toggle = false
} else {
timer.invalidate()
babyImage.image = UIImage(named: "WaWa1.png")
cryButton.setTitle("Wa-Waaaaa!", forState: UIControlState.Normal)
toggle = true
}
}
func doanimation() {
babyImage.image = UIImage(named: "WaWa\(counter).png")
if (counter == (numImages)) {
counter = 1
} else {
++counter
}
}
override func viewDidLayoutSubviews() {
babyImage.center = CGPointMake(babyImage.center.x - 400, babyImage.center.y)
}
override func viewDidAppear(animated: Bool) {
UIView.animateWithDuration(2, animations: { () -> Void in
self.babyImage.center = CGPointMake(self.babyImage.center.x + 400, self.babyImage.center.y)
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I finally find the problem. It is not caused by the timer, the timer is totally fine. the problem is caused by viewDidLayoutSubviews being called when you set the button title. You are using auto layout, and you are using the intrinsic content size for the button, right? And since the two title has different length so when you set the title, the button's frame will be changed, hence it will be layout again and then viewDidLayoutSubviews will be called. And you set the center value of the imageView inside viewDidLayoutSubviews, so basically when you set the title the image will move 400 points left to its original spot which I guess is out of the screen. Please note: if the image has different size, when you call imageView.image = UIImage(named: "image.png") will also call viewDidLayoutSubviews. I think all the images you are using has same size, thats why when the timer runs viewDidLayoutSubviews was not called. Here is a good answer which explains when does viewDidLayoutSubviews get called. I will let yourself to figure out the proper solution, OK? :)
Actually there is a better way to animate a UIImageView with an array of images, you could probably try this and remove the timer.
babyImage.animationImages = #[image1,image2,image3,image4,image5,image6,image7,image8]
babyImage.animationDuration = 1.6
// There are 8 images, so each image occupies 1.6 / 8 = 0.2 secs
babyImage.startAnimating()
// Use babyImage.stopAnimating() to stop the animation

Swift Fade In Animation for Background Animation between A Single View to a PageView Controller

So I am trying to create a fade in animation for a UI Image that is in a page view scroller after a button is clicked in the main view controller. This is my main storyboard.
class MainWorkoutViewController: UIViewController {
// Outlet used in storyboard
#IBOutlet var scrollView: UIScrollView?;
override func viewDidLoad() {
super.viewDidLoad();
func scrollViewDidEndDragging(MainWorkoutViewController: UIScrollView,
withVelocity: CGPoint,
targetContentOffset : UnsafeMutablePointer<CGPoint>){
}
// 1) Create the three views used in the swipe container view
var AVc :AViewController = AViewController(nibName: "AViewController", bundle: nil);
var BVc :BViewController = BViewController(nibName: "BViewController", bundle: nil);
var CVc :CViewController = CViewController(nibName: "CViewController", bundle: nil);
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(CVc);
self.scrollView!.addSubview(CVc.view);
CVc.didMoveToParentViewController(self);
self.addChildViewController(BVc);
self.scrollView!.addSubview(BVc.view);
BVc.didMoveToParentViewController(self);
self.addChildViewController(AVc);
self.scrollView!.addSubview(AVc.view);
AVc.didMoveToParentViewController(self);
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = BVc.view.frame;
adminFrame.origin.x = adminFrame.width;
AVc.view.frame = adminFrame;
var BFrame :CGRect = AVc.view.frame;
BFrame.origin.x = 2*BFrame.width;
CVc.view.frame = BFrame;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = 3 * self.view.frame.width
var scrollHeight: CGFloat = self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight)
var frame: CGRect = self.view.frame
frame.origin.x = frame.size.width * CGFloat(1);
frame.origin.y = 0;
self.scrollView!.scrollRectToVisible(frame, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
self.tabBarController?.selectedIndex = 2
}
}
This is the .swift file for the first Viewcontroller that I have, which contains the image I want to fade in when the screen loads.
import UIKit
class AViewController: UIViewController {
#IBOutlet var Background: UIImageView!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
UIView.animateWithDuration(1.5, animations: {
self.Background.alpha = 1.0
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I looked around for a way to do it and that is why I have the animatedWithDuration, but instead all I am getting is the screen swiping up from the bottom of the phone. Any ideas?
Try setting the alpha to 0.0 before the UIView.animateWithDuration function.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.background.alpha = 0.0
UIView.animateWithDuration(1.5, animations: {
self.background.alpha = 1.0
})
}
Please note that viewDidAppear is not called after you have scrolled to a view in the scrollview. It is called when the view is added to the view hierarchy. You have to manually write the code for making the label appear using scrollView delegate functions if you want to make it appear when you scroll with your fingers or scroll automatically later.
You can do a cross dissolve animation instead of scrolling by doing
CATransaction.flush()
self.scrollView.contentOffset = CGPointMake(self.view.frame.width,0)
UIView.transitionWithView(self.scrollView, duration: 1.0, options:
.TransitionCrossDissolve, animations: { () -> Void in
}) { (finished) -> Void in
}
Either use CATransactionFlush or put the code inside viewDidAppear.
Remove the scrollView.scrollRectToVisible code.

Resources