13

I have created an app which loads up and has a Login / Signup page etc using swift. Currently I have an image as a background but would like to add code so there is a gif / mov playing in the background like in apps like vine or instagram.

How can I integrate the video in with my current code? I am also very new to this so have been following tutorials. Also if anyone knows how I can remove the parse logo, that would also be helpful.

The video appears but in front of the UI on my storyboard! How can I get them to appear in front of the background GIF?

Below is my code that I currently have for my Sign In view controller.

import UIKit
import Foundation

class SignInViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var userName: UITextField!
@IBOutlet weak var password: UITextField!

@IBOutlet weak var errorLabel: UILabel!

override func viewDidLoad() {

       super.viewDidLoad()

    let filePath = NSBundle.mainBundle().pathForResource("beachwater", ofType: "gif")
    let gif = NSData(contentsOfFile: filePath!)

    let webViewBG = UIWebView(frame: self.view.frame)
    webViewBG.loadData(gif!, MIMEType: "image/gif", textEncodingName: "UTF-8", baseURL: NSURL(string: "")!)
    webViewBG.userInteractionEnabled = false;
    self.view.addSubview(webViewBG)


    userName.delegate = self
    password.delegate = self
}


@IBAction func signInTouched(sender: UIButton) {

    let signin = SignIn(user: userName.text!, pass: password.text!)

    do {
        try signin.signInUser()
        self.dismissViewControllerAnimated(true, completion: nil)


    } catch let error as Error {
        errorLabel.text = error.description
    } catch {
        errorLabel.text = "Sorry something went\n wrong please try again"
    }

}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.view.endEditing(true)

}

}
Robert S
  • 193
  • 2
  • 2
  • 11

6 Answers6

49

The following code allows you to add a video background for your view controller.

It is written in Swift and plays mp4 video files.

For Swift 5.

import AVFoundation

class VideoBackgroundController: UIViewController {
    var avPlayer: AVPlayer!
    var avPlayerLayer: AVPlayerLayer!
    var paused: Bool = false

    override func viewDidLoad() {

        let theURL = Bundle.main.url(forResource:"my_video_file", withExtension: "mp4")

        avPlayer = AVPlayer(url: theURL!)
        avPlayerLayer = AVPlayerLayer(player: avPlayer)
        avPlayerLayer.videoGravity = .resizeAspectFill
        avPlayer.volume = 0
        avPlayer.actionAtItemEnd = .none

        avPlayerLayer.frame = view.layer.bounds
        view.backgroundColor = .clear
        view.layer.insertSublayer(avPlayerLayer, at: 0)

        NotificationCenter.default.addObserver(self,
                                           selector: #selector(playerItemDidReachEnd(notification:)),
                                           name: .AVPlayerItemDidPlayToEndTime,
                                           object: avPlayer.currentItem)
    }

    @objc func playerItemDidReachEnd(notification: Notification) {
        let p: AVPlayerItem = notification.object as! AVPlayerItem
        p.seek(to: .zero)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        avPlayer.play()
        paused = false
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        avPlayer.pause()
        paused = true
    }
}
Amr Hossam
  • 2,313
  • 1
  • 22
  • 23
  • Works great. Question. Did you have any issues getting it to load right away? Mine currently just pops in after a couple seconds – Unome Dec 08 '16 at 19:56
  • How I can add a transparency layer? – JCarlosR Feb 22 '17 at 14:16
  • This is awesome, only current issue is it pauses playing music, on music play the video pauses - but this is probably expected due to the AVPlayer implmentation – Phil Hudson Jul 06 '17 at 21:33
  • @JCarlos For add gradient, comment `//view.backgroundColor = .clear` and add [link](https://stackoverflow.com/a/54556076/5869217) – Álvaro Agüero Feb 06 '19 at 14:35
2

This works, replace all of the code that you just put there with this:

     let filePath = NSBundle.mainBundle().pathForResource("beach_water", ofType: "gif")
     let gif = NSData(contentsOfFile: filePath!)

     let webViewBG = UIWebView(frame: self.view.frame)
     webViewBG.loadData(gif!, MIMEType: "image/gif", textEncodingName: "UTF-8", baseURL: NSURL(string: "")!)
     webViewBG.userInteractionEnabled = false;
     self.view.addSubview(webViewBG)

That is all tested and works 100%

EDIT Swift 3 and have the Gif in the background:

let filePath = Bundle.main.path(forResource: "beach_water", ofType: "gif")
let gif = NSData(contentsOfFile: filePath!)
let webViewBG = UIWebView(frame: self.view.frame)
webViewBG.load(gif! as Data, mimeType: "image/gif", textEncodingName: "UTF-8", baseURL: NSURL(string: "")! as URL)
webViewBG.isUserInteractionEnabled = false
webViewBG.layer.zPosition = -2.0
self.view.addSubview(webViewBG)
Zander
  • 414
  • 2
  • 16
  • So there are no errors with this code which is excellent! But I am now getting the problem that the gif won't appear behind my text. It is just blank. I am using Parse for the sign in so I wonder if it is to do with that and I need another line of code to show the video behind the buttons. I will put a screenshot up so you can see my results. – Robert S Oct 02 '15 at 08:18
  • it works when I put it alone in a view controller with nothing else in it! Hmm I am confused as to why it won't go into the background. – Robert S Oct 02 '15 at 08:59
  • Ok, make sure the code is the first line in the viewDidLoad() method. – Zander Oct 02 '15 at 11:27
  • No luck. I think it didn't work because it is a PFLogInViewController for parse use... – Robert S Oct 02 '15 at 15:15
  • so this code is great but now it won't appear behind all my other items in the storyboard :/ – Robert S Oct 07 '15 at 18:20
  • The video appears but in front of the UI of my storyboard! How can I get the UI to appear in front of the background GIF? I have amended the code so you can see what I now have. – Robert S Oct 07 '15 at 18:25
  • Set the z position like this: webViewBG.zposition = 2.0 – Zander Oct 07 '15 at 18:26
  • Where would that go exactly? – Robert S Oct 07 '15 at 18:28
  • Before you add the webViewBG to the subview – Zander Oct 07 '15 at 18:29
  • Thanks for your help. Figured it out. The code needs to be slightly different... webViewBG.layer.zPosition = -2.0 – Robert S Oct 08 '15 at 07:31
0

Really simple, first drag your gif into your Assets.xcassets. Second get the file in code(probably in a configure view method.

    var filePath = NSBundle.mainBundle().pathForResource(“YourImageNameHere”, ofType: “gif”)
    var gif = NSData(contentsOfFile: filePath)
  1. Create a UIWebView and add the GIF NSData as its data source.

    var webViewBG = UIWebView(frame: self.view.frame)
    webViewBG.loadData(gif, MIMEType: “image/gif”, textEncodingName: nil, baseURL: nil)
    webViewBG.userInteractionEnabled = false;
    self.view.addSubview(webViewBG)
    

And there you go, just make sure to have the webView behind your Buttons and other UIElements

Zander
  • 414
  • 2
  • 16
  • Seems simple but where in my code would that all go? – Robert S Oct 01 '15 at 13:54
  • In the replace the background Image with this code in the viewDidLoad – Zander Oct 01 '15 at 14:07
  • This is the error I am getting... Nil is not compatible with expected argument type 'String'. – Robert S Oct 01 '15 at 14:17
  • On what line was that? – Zander Oct 01 '15 at 14:22
  • Both of these lines have problems: var gif = NSData(contentsOfFile: filePath) webViewBG.loadData(gif, MIMEType: "image/gif", textEncodingName: nil, baseURL: nil) – Robert S Oct 01 '15 at 14:45
  • Try var gif = NSData(contentsOfFile: filepath!) that should fix it – Zander Oct 01 '15 at 15:15
  • now it says; use of unresolved identifier 'filepath' – Robert S Oct 01 '15 at 15:36
  • I have provided a screenshot above to show where I have put it and the problems. – Robert S Oct 01 '15 at 16:13
  • Oh your file path can't have .gif on it because you use oftype: gif so that automatically adds that onto it. – Zander Oct 01 '15 at 16:16
  • Deleted the .gif and it still has the error. I have replaced the screenshot – Robert S Oct 01 '15 at 16:22
  • Try this: You need to implement do try catch error handling. Try like this: if let path = NSBundle.mainBundle().pathForResource("Chapters", ofType: "txt"){ do { let stringFromFile = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding) var chapters: [String] = stringFromFile.componentsSeparatedByString("@") chapters.removeAtIndex(0) } catch { print((error)) } } – Zander Oct 01 '15 at 16:50
  • But fill in your file path and your details – Zander Oct 01 '15 at 16:51
  • included a new screenshot. Still same error. I wonder if it is a bug! – Robert S Oct 01 '15 at 17:00
  • Give me a few minutes and I will write it out for you, all tested and everything – Zander Oct 01 '15 at 17:14
0

This is the complete solution. The negative z position is important!

let filePath = NSBundle.mainBundle().pathForResource("Lake", ofType: "gif")

let gif = NSData(contentsOfFile: filePath!)

let webViewBG = UIWebView(frame: self.view.frame)

webViewBG.loadData(gif!, MIMEType: "image/gif", textEncodingName: "UTF-8", baseURL: NSURL(string: "")!)

webViewBG.userInteractionEnabled = false
webViewBG.layer.zPosition = -2.0
self.view.addSubview(webViewBG)
MacInnis
  • 760
  • 9
  • 19
0

Thanks! To add gradient :

let gradient: CAGradientLayer = CAGradientLayer()
    gradient.colors = [self.hexStringToUIColor(hex: "#141414").cgColor,self.hexStringToUIColor(hex: "#323232").cgColor]
    gradient.locations = [0.0,1.0]
    gradient.opacity = 0.8
    gradient.startPoint = CGPoint(x: 1.0, y: 0.0)
    gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
    gradient.frame = viewLogin.layer.frame
    viewLogin.layer.insertSublayer(gradient, at: 0)

hexStringToUIColor method :

var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

    if (cString.hasPrefix("#")) {
        cString.remove(at: cString.startIndex)
    }

    if ((cString.count) != 6) {
        return UIColor.gray
    }

    var rgbValue:UInt32 = 0
    Scanner(string: cString).scanHexInt32(&rgbValue)

    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
Álvaro Agüero
  • 4,494
  • 1
  • 42
  • 39
0

I wrote a Swift UIView subclass called SDLoopingVideoView that plays and loops any compatible AVPlayer video file and automatically scales it to fill the view. It can be entirely setup in Interface Builder This work great as a video background. You can find it on Github here: SDLoopingVideoView

Solsma Dev
  • 481
  • 6
  • 22