【Swift】UIViewで左右からスライドを出現させる

 

解説

 

・3つのStoryBoardを用いる

・色付けしたUILabelをスライドにした

・ContainerViewでViewの描画領域を確保する

・"Left"または"Right"のボタンを押すと、それぞれに対応するStoryBoardのUIViewControllerがアニメーション付きで描画される

・その時、Leftなら左から、Rightなら右側から、出てくるように見える

・LeftViewController,RightViewControllerには一切の記述なし

 

・UIScreen.main.bounds.width:スクリーンの幅

・UIScreen.main.bounds.height:スクリーンの高さ

・Left (Right) InitFrame:初期のframe(座標位置)

・containerViewDispFrame:Main.StoryBoard(全てのUI部品を司るUIViewController)のframe(つまり原点)

 

ストーリーボード

 

f:id:nekokichi_yos2:20181011144320p:plain

f:id:nekokichi_yos2:20181011144323p:plain

f:id:nekokichi_yos2:20181011144325p:plain

 

ソースコード

import UIKit

class ViewController: UIViewController {
    
    //MainのViewControllerの右側へViewController移動した座標
    let RightViewInitFrame = CGRect(x: UIScreen.main.bounds.width, y: 0, 
                                        width: UIScreen.main.bounds.width,  
                                        height: UIScreen.main.bounds.height)
    
    //MainのViewControllerの左側へViewController移動した座標
    let LeftViewInitFrame = CGRect(x: -UIScreen.main.bounds.width, y: 0,  
                                        width: UIScreen.main.bounds.width, 
                                        height: UIScreen.main.bounds.height)
    
    ////MainのUIViewControllerと同じ座標
    let containerViewDispFrame = CGRect(x: 0, y: 0,
                                        width: UIScreen.main.bounds.width,
                                        height: UIScreen.main.bounds.height)
    
    @IBOutlet weak var RightView: UIView! {
        didSet {
            //StoryBoardのインスタンス
            let vc = UIStoryboard(name: "Right",
                                  bundle: nil).instantiateInitialViewController()
            RightView.frame = RightViewInitFrame
            RightView.addSubview(vc!.view)
        }
    }
    
    @IBOutlet weak var LeftView: UIView! {
        didSet {
            let vc = UIStoryboard(name: "Left",
                                  bundle: nil).instantiateInitialViewController()
            LeftView.frame = LeftViewInitFrame
            LeftView.addSubview(vc!.view)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    //画面をタップした時
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        
        //画面を押した時に表示されているviewがRightかLeftだった場合
        for touch in touches {
            if let view = touch.view {
                //スライドを引っ込める
                traditionalVC(tag: view.tag)
            }
        }
        
    }
    
    //スライドを引っ込める(元に戻す)
    func traditionalVC(tag: Int) {
        
        //もしRightボタンを押したら
        if tag == 1 {
            RightAnimateInitFrame()
        }
        //もしLeftボタンを押したら
        else if tag == 2{
            LeftAnimateInitFrame()
        }
        
    }

    @IBAction func RightButton(_ sender: Any) {
        
        //既に左スライドが出てるなら
        //引っ込める
        if LeftView.frame == containerViewDispFrame {
            LeftAnimateInitFrame()
        }
        
        //もしまだ出てないなら右スライドが出てないなら
        //スライドを出す
        if RightView.frame != containerViewDispFrame {
            UIView.animate(withDuration: 0.3, animations: {
                self.RightView.frame = self.containerViewDispFrame
            })
        //既に右スライドが出てるなら
        //スライドを引っ込める
        } else {
            RightAnimateInitFrame()
        }
        
    }
    
    @IBAction func LeftButton(_ sender: Any) {
        
        if RightView.frame == containerViewDispFrame {
            RightAnimateInitFrame()
        }
        
        if LeftView.frame != containerViewDispFrame {
            UIView.animate(withDuration: 0.3, animations: {
                self.LeftView.frame = self.containerViewDispFrame
            })
        } else {
            LeftAnimateInitFrame()
        }
        
    }
    
    //右スライドを引っ込める
    func RightAnimateInitFrame() {
        UIView.animate(withDuration: 0.3, animations: {
            self.RightView.frame = self.RightViewInitFrame
        })
    }
    
    //左スライドを引っ込める
    func LeftAnimateInitFrame() {
        UIView.animate(withDuration: 0.3, animations: {
            self.LeftView.frame = self.LeftViewInitFrame
        })
    }
    
}

 

【Swift】TableViewを使ったパララックスアニメーション

 

解説

 

※注意

ソースコードが複雑で、僕もよくわかってない

 

・”パララックス”という視覚効果

↓参考動画

youtu.be

・セルをスクロールすると、セル内のImageViewがパララックスの視覚効果をもたらす

 

ストーリーボード

 

f:id:nekokichi_yos2:20181011141420p:plain

 

ソースコード

import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
    
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        
        tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
        
        tableView.reloadData()
        
        paralex()
        
    }
    
    //画像の視覚効果を実装する
    func paralex() {
        guard let tableViewRows = tableView.indexPathsForVisibleRows else { return }
        for indexPath in tableViewRows {
            //セルを生成
            guard let cell = tableView.cellForRow(at: indexPath) as? CustomCell else { continue }
            
            //indexPathに該当するセルのdraw(描く)area(領域)をCGRectで返す
            let rect = tableView.rectForRow(at:indexPath)
            //rectでtableViewに表示するための座標を読み込む
            let rectInTable = tableView.convert(rect, to: tableView.superview)
            //??
            let offset = rectInTable.origin.y + rectInTable.height / 2
            //tableViewの数だけoffsetを割る?
            let offsetRatio = offset / tableView.bounds.height
            
            //セルのimageViewのframe(描画後の座標)を取得
            var imageViewRect = cell.paralexImageView.frame
            
            //??
            imageViewRect.origin.y = offsetRatio * 100 * -1
            //??
            cell.paralexImageView.frame = imageViewRect
            
        }
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 8
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        
        return cell
        
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 165
    }
    
    //スクロールした時に視覚を変化させる
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        paralex()
    }

}

 

ソースコード2

import UIKit

class CustomCell: UITableViewCell {
    
    //ImageViewで紐付けすると、エラーがでる
    //既にカスタムクラスにはimageViewがあるらしいから
    //同じ名前ではなくimageView以外の名前に推奨
    @IBOutlet weak var paralexImageView: UIImageView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    
}

 

【Swift】MPMusicPlayerで音楽プレイヤーを作る

 

完成図

 

f:id:nekokichi_yos2:20181009225259p:plain
f:id:nekokichi_yos2:20181009225219p:plain

 

解説

 

・プロセス

  1. 起動直後にライブラリから曲を選択させられる
  2. 選択して、左上の完了を押すと、プレイヤー画面へと移行
  3. 再生/停止ボタンを押せば、再生/停止ができる
  4. 中央のバー(ScrubBar)で好きな再生位置に移動できる
  5. もし他の曲を再生したいなら、下の”選曲画面へ”を押せばいい

 

・MPMusicPlayerで音楽プレイヤーを実装

・他にもAVFoundationを使う方法もある

・曲の再生位置は、player.currentPlaybackTime、の数値

・再生/停止をするたびに、再生位置をTimeInterval型の変数に保存し、currentPlaybackTimeに入れる作業を繰り返す

・timer関数でScrubBarを0.5秒間隔で移動させている

 

・めっちゃ参考になった記事

[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(MPMusicPlayerController使用) – nackpan Blog

 

・もっとおしゃれな音楽プレイヤーを作るなら、こちらもおすすめ

qiita.com

 

 

ストーリーボード

 

f:id:nekokichi_yos2:20181009225336p:plain

 

ソースコード

 

import UIKit
import MediaPlayer

class ViewController: UIViewController,MPMediaPickerControllerDelegate {
    
    
    @IBOutlet weak var imageView: UIImageView!
    
    @IBOutlet weak var songname: UILabel!
    
    @IBOutlet weak var artistname: UILabel!
    
    @IBOutlet weak var playButton: UIButton!
    
    @IBOutlet weak var scrubBar: UISlider!
    
    //MediaPlayerのインスタンスを作成
    var player:MPMusicPlayerController!
    
    //タイマー変数を定義
    var timer = Timer()
    
    //次に再生するか一時停止するかを判断
    var playorpause = 0
    
    //曲が再生される前かされた後かを判定
    var flag = 0
    
    //曲の現在位置を一次的に保持
    var currenttime = 0.0
    
    //曲の長さを保持する変数
    var timeinterval = TimeInterval()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //プレイヤーの準備
        player = MPMusicPlayerController.applicationMusicPlayer
        
        //??
        let notificationcenter = NotificationCenter.default
        notificationcenter.addObserver(self, selector: #selector(type(of: self).nowPlayingItemChanged(notification:)), name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange, object: player)
        
        //初期化
        scrubBar.value = 0.0
        //再生されてないのにタップしてエラーが出るのを防ぐため
        scrubBar.isHidden = true
        
        //初期画面をピッカー画面にする
        //誤って、再生ボタンを押してエラーが出るのを防ぐため
        //MPMediaPickerのインスタンス
        let picker = MPMediaPickerController()
        //ピッカーのデリゲートを設定
        picker.delegate = self
        //複数選択を不可にする
        picker.allowsPickingMultipleItems = true
        //ピッカー画面を表示
        present(picker, animated: true, completion: nil)
        
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    //再生中の曲が変更された時に実行
    @objc func nowPlayingItemChanged(notification:NSNotification) {
        //もし再生できる状態なら
        if let playingitem = player.nowPlayingItem {
            updatesong(mediaItem: playingitem)
        }
    }
    
    //使用した〇〇を破棄する
    deinit {
        let notificationcenter = NotificationCenter.default
        notificationcenter.removeObserver(self, name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange, object: player)
        //
        player.endGeneratingPlaybackNotifications()
    }
    
    //曲の情報を表示する
    func updatesong(mediaItem: MPMediaItem) {
        
        //曲情報を表示
        songname.text = mediaItem.albumTitle ?? "不明なタイトル"
        artistname.text = mediaItem.albumArtist ?? "不明なアーティスト"
        timeinterval = mediaItem.playbackDuration
        //アートワークを表示
        if let artwork = mediaItem.artwork {
            //アートワークの枠サイズを設定
            let image = artwork.image(at: imageView.bounds.size)
            //imageviewにがアートワークを設定する
            imageView.image = image
        } else {
            //もしアートワークがなければ、何も表示しない
            imageView.image = nil
        }
        
    }
    
    //ピッカー画面で曲が選択された時
    func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        //プレイヤーを止める
        player.stop()
        //選択した曲をplayerにセット
        player.setQueue(with: mediaItemCollection)
        //選択した曲の情報をラベルやイメージビューにセット
        if let mediaitem = mediaItemCollection.items.first {
            updatesong(mediaItem: mediaitem)
        }
        //ピッカーを閉じて、破棄する
        dismiss(animated: true, completion: nil)
    }
    
    //スライダーの位置を曲の再生位置と同期する
    @objc func updateslider(){
        self.scrubBar.setValue(Float(self.player.currentPlaybackTime), animated: true)
    }
    
    //曲が選択されなかった時
    func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) {
        dismiss(animated: true, completion: nil)
    }
    
    //選択画面へを押した場合
    @IBAction func pick(_ sender: Any) {
        //flag変数を初期化
        flag = 0
        //timerを破棄する
        timer.invalidate()
        //プレイヤーを一旦停止する
        player.pause()
        //曲が停止されたことを示す
        playButton.setImage(UIImage(named: "play.png"), for: UIControl.State())
        //MPMediaPickerのインスタンス
        let picker = MPMediaPickerController()
        //ピッカーのデリゲートを設定
        picker.delegate = self
        //複数選択を不可にする
        picker.allowsPickingMultipleItems = true
        //ピッカー画面を表示
        present(picker, animated: true, completion: nil)
    }
    
    @IBAction func play(_ sender: Any) {
        //もし停止中なら
        if playorpause == 0{
            //保持した位置を代入
            player.currentPlaybackTime = currenttime
            //再生
            player.play()
            //再生中であることを示す
            playorpause = 1
            //画像を再生のマークに
            playButton.setImage(UIImage(named: "pause.png"), for: UIControl.State())
            //もしまだ1度も再生されてなければ
            if flag == 0 {
                scrubBar.isHidden = false
                scrubBar.maximumValue = Float(timeinterval)
                flag = 1
            }
            //スライダーと曲を同期
            timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, 
               selector: #selector(updateslider), userInfo: nil, repeats: true)
        }
        //もし曲が再生中なら
        else {
            //停止した位置を保持
            currenttime = player.currentPlaybackTime
            //タイマーを停止し、曲を一時停止
            timer.invalidate()
            player.pause()
            playorpause = 0
            playButton.setImage(UIImage(named: "play.png"), for: UIControl.State())
        }
    }
    
    //次の曲へ
    @IBAction func next(_ sender: Any) {
        player.skipToNextItem()
        playButton.setImage(UIImage(named: "play.png"), for: UIControl.State())
    }
    
    //前の曲へ
    @IBAction func back(_ sender: Any) {
        player.skipToPreviousItem()
        playButton.setImage(UIImage(named: "play.png"), for: UIControl.State())
    }
    
    //スライダーを移動した位置を曲の再生位置に設定
    @IBAction func scrubAction(_ sender: Any) {
        player.currentPlaybackTime = TimeInterval(scrubBar.value)
        currenttime = player.currentPlaybackTime
    }
    
}

【Swift】ImageViewの使い方

 

完成図

 

f:id:nekokichi_yos2:20181009224603g:plain

 

解説

 

・プロセス

  1. 1つ目の画像が表示される
  2. 画面をタップ
  3. (4つ目まで繰り返し)
  4. 4つ目の画像をタップ
  5. (最初に戻る)

 

・viewDidLoad()する前にimage_arrayに画像を入れたかったが、エラーが出たので断念。

・タップすると画像が切り替わる動作は、touchesBeganで実装

 

ストーリーボード

 

f:id:nekokichi_yos2:20181009224551p:plain

 

ソースコード

 

import UIKit

class ViewController: UIViewController {
    
    
    @IBOutlet weak var ImageView: UIImageView!
    
    //画像を用意する
    let image0 = UIImage(named: "壁紙1.jpg")
    let image1 = UIImage(named: "壁紙2.jpg")
    let image2 = UIImage(named: "壁紙3.jpg")
    let image3 = UIImage(named: "壁紙4.jpg")
    
    //複数の画像を入れる配列
    var image_array = [UIImage]()
    
    //カウンタ変数
    var count = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //画像を格納した配列を用意
        image_array = [image0!,image1!,image2!,image3!]
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //タップ時に呼ばれる
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        ImageView.image = image_array[count]
        
        //もし4つ目の画像になったら
        if count == 3 {
            count = -1
        }
        
        //カウンタ変数を更新
        count += 1
        
    }

}