LoginSignup
0
1

More than 3 years have passed since last update.

ストーリーボードをつかわず、再生↔一時停止をToolbarで書くとこうなるサンプル(Playgroundサンプル付き)

Posted at

はじめに

オーディオプレーヤーの再生↔一時停止のようにツールバーをつくるとき、みなさんはどのように書いていますか。:thinking:

  • Storyboardをつかわない
  • Swift4
  • NavigationControllerをつかう

こんな条件のときのサンプルが見つけられなかったので、いろいろためしながら実装した方法を紹介したいとおもいます。

実行結果は、こんな感じになります。
audio_playground.gif
この記事の最後に、Playgroundにコピペすると動作するコードを載せていますのでそちらも参考になれば:relaxed:

前準備

ビューの作成時に、self.toolbarItemsをセットしておく必要があります。
NavigationControllerにツールバーを表示させる方法は、NavigationControllerのToolbarを特定のViewControllerでのみ有効にする - Qiitaを参考にしてみてください。

ボタンをトグルするコード

ボタンのオブジェクトはひとつにしてbarButtonSystemItem.play.pauseでトグルすればいいのでは?とおもったのですが、再生ボタンと一時停止ボタンの2つのオブジェクトを用意して差し替えるのがベターな方法みたいです。

private var audioPlaying = false

// MARK: ツールバーのアイテム
private var uiPlayButtonItem : UIBarButtonItem {
  let button = UIBarButtonItem(
    barButtonSystemItem: .play,
    target: self,
    action: #selector(onButton(_:)))
  button.tag = 1
  return button
}
private var uiPauseButtonItem : UIBarButtonItem {
  let button = UIBarButtonItem(
    barButtonSystemItem: .pause,
    target: self,
    action: #selector(onButton(_:)))
  button.tag = 1 // 置換するのでtagはおなじ
  return button
}

private lazy var uiButtonItems: [UIBarButtonItem] = {

  let flexibleItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
  flexibleItem.tag = 0
  return [
    flexibleItem,
    uiPauseButtonItem, // 最初は再生
    flexibleItem,
  ]
}()

@objc func onButton(_ sender: UIBarButtonItem) {
  // 再生ボタンを差し替えるので、index位置を取得する
  guard let buttonIndex = self.uiButtonItems.firstIndex(
    where: {$0.tag == 1}
  ) else {
    print( "再生ボタンのインデックスが取得できてません")
    return
  }

  if self.audioPlaying {
    self.audioPlaying = false
    self.toolbarItems?[buttonIndex] = self.uiPlayButtonItem
    return
  }

  self.audioPlaying = true
  self.toolbarItems?[buttonIndex] = self.uiPauseButtonItem
}

Playgroundで試せるコード

image.png

以下を実行すると、冒頭のスクショのような動作になります。

import UIKit
import XCPlayground
import PlaygroundSupport

class ViewController: UIViewController {
    private var audioPlaying = false
    let label = UILabel()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        label.textAlignment = .center
        view.addSubview(label)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        label.frame = view.bounds
    }

    // ツールバーを表示する
    override func viewWillAppear(_ animated: Bool) {
        self.toolbarItems = self.uiButtonItems
        self.updateButton()
        self.updateLabel()
        self.navigationController?.setToolbarHidden(false, animated: false)
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.navigationController?.setToolbarHidden(true, animated: false)
        super.viewWillDisappear(animated)
    }

    // MARK: ツールバーのアイテム
    private var uiPlayButtonItem : UIBarButtonItem {
      let button = UIBarButtonItem(
        barButtonSystemItem: .play,
        target: self,
        action: #selector(onButton(_:)))
      button.tag = 1
      return button
    }
    private var uiPauseButtonItem : UIBarButtonItem {
      let button = UIBarButtonItem(
        barButtonSystemItem: .pause,
        target: self,
        action: #selector(onButton(_:)))
      button.tag = 1 // 置換するのでtagはおなじ
      return button
    }

    private lazy var uiButtonItems: [UIBarButtonItem] = {

      let flexibleItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
      flexibleItem.tag = 0
      return [
        flexibleItem,
        uiPauseButtonItem, // 最初は再生
        flexibleItem,
      ]
    }()

    func updateLabel() {
        label.text = self.audioPlaying ? "playing..." : "pause"
    }

    func togglePlayState() {
        self.audioPlaying = !self.audioPlaying
    }

    func updateButton() {
        // 再生ボタンを差し替えるので、index位置を取得する
        guard let buttonIndex = self.uiButtonItems.firstIndex(
          where: {$0.tag == 1}
        ) else {
          print( "再生ボタンのインデックスが取得できてません")
          return
        }
        if self.audioPlaying {
          self.toolbarItems?[buttonIndex] = self.uiPauseButtonItem
          return
        }
        self.toolbarItems?[buttonIndex] = self.uiPlayButtonItem
    }

    @objc func onButton(_ sender: UIBarButtonItem) {
        self.togglePlayState()
        self.updateButton()
        self.updateLabel()
    }
}

var ctrl = ViewController()
let navigationController = UINavigationController(rootViewController: ctrl)
navigationController.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = navigationController.view
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1