user5209290
user5209290

Reputation:

UIBarButtonItem changing image for Play/Pause button

I'm trying to make a play/pause button that toggles between custom images as it is pressed. Here is a snippet of the code.

Everything works fine but the button doesn't change. I've also tried using the .image property instead of the .setBackGroundImage method but then the button just goes blank on click.

Here is the code

import UIKit
import AVFoundation

class ViewController: UIViewController {

var audioPlayer = AVAudioPlayer()

var pauseImage:UIImage?
var playImage:UIImage?

@IBOutlet weak var btnPlayPause: UIBarButtonItem!

@IBOutlet weak var sldVolume: UISlider!

@IBAction func sldVolumeChanged(sender: AnyObject) {

    audioPlayer.volume = sldVolume.value

}

@IBAction func actPressedPlayPause(sender: AnyObject) {

    if audioPlayer.playing {
        audioPlayer.pause()
        btnPlayPause.setBackgroundImage(playImage, forState: .Normal, barMetrics: .Default)

    } else {
        audioPlayer.play()
        btnPlayPause.setBackgroundImage(pauseImage, forState: .Normal, barMetrics: .Default)
    }

}

@IBAction func actStopPressed(sender: AnyObject) {

    audioPlayer.stop()
    audioPlayer.currentTime = 0

}

override func viewDidLoad() {
    super.viewDidLoad()

    var pauseImagePath = NSBundle.mainBundle().pathForResource("pause", ofType: "png")
    pauseImagePath = pauseImagePath!.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    pauseImage = UIImage(contentsOfFile: pauseImagePath!)

    var playImagePath = NSBundle.mainBundle().pathForResource("play", ofType: "png")
    playImagePath = playImagePath!.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    playImage = UIImage(contentsOfFile: pauseImagePath!)



    var audioPath = NSBundle.mainBundle().pathForResource("minuetcminor", ofType: "mp3")

    audioPath = audioPath!.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

    var error : NSError? = nil

    audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(string: audioPath!), error: &error)

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Upvotes: 9

Views: 7910

Answers (4)

Vikas Dadheech
Vikas Dadheech

Reputation: 1720

Try using below line of code:

btnPlayPause.setImage(image, forState: .Normal)

this works for me.

Upvotes: -2

Makalele
Makalele

Reputation: 7531

Seems like this question has got a lot of strange answers. The truth is there's no non-hacky way to change an image in already existing UIBarButtonItem. Instead, unfortunately, you have to re-create it. I've made a helper method to do this:

func changeBarButtonItemImage(_ item: UIBarButtonItem, image: UIImage, navItem: UINavigationItem) -> UIBarButtonItem? {

    let buttonItem = UIBarButtonItem(image: image, style: item.style, target: item.target, action: item.action)
    buttonItem.isEnabled = item.isEnabled

    if let leftIndex = navItem.leftBarButtonItems?.index(of: item) {
        var items: [UIBarButtonItem] = navItem.leftBarButtonItems!
        items[leftIndex] = buttonItem
        navItem.leftBarButtonItems = items
        return buttonItem
    }

    if let rightIndex = navItem.rightBarButtonItems?.index(of: item) {
        var items: [UIBarButtonItem] = navItem.rightBarButtonItems!
        items[rightIndex] = buttonItem
        navItem.rightBarButtonItems = items
        return buttonItem
    }

    return nil
}

Usage:

if let image = UIImage(named: showingFilter ? "icon_filter_active.png" : "icon_filter.png") {
    if let buttonItem = changeBarButtonItemImage(self.filterButton, image: image, navItem: navigationItem) {
        self.filterButton = buttonItem
    }
}

Take note that I also copy isEnabled property, because, in my case, in some situations, I was changing button icon while in the disabled state.

Upvotes: 1

Anjan Biswas
Anjan Biswas

Reputation: 7932

The @IBAction should use sender as UIButton instead of AnyObject or Any. Also, once that is done, the button can be directly accessed from inside the function using sender. (This is Swift 3)

@IBAction func actPressedPlayPause(sender: UIButton) {

    if audioPlayer.playing {
        audioPlayer.pause()
        sender.setBackgroundImage(UIImage(named: "playimage.png"), for: .normal)

    } else {
        audioPlayer.play()
        sender.setBackgroundImage(UIImage(named: "pauseimage.png"), for: .normal)
    }

}

Upvotes: 0

jackchmbrln
jackchmbrln

Reputation: 1713

had the same problem here! Had two of us confused as to why it wasn't working, I think it's a change in Swift 2/Xcode 7 beta

Just do this:

btnPlayPause.image = UIImage(named: "myImage.png")

Hope that helps!

Upvotes: 19

Related Questions