更改 UIScrollView 上的视图,以便音乐更改

Change views on UIScrollView so music changes

我有一个 UIScrollView 设置,但是当我改变视图时,音乐不会停止。怎样才能让音乐在您改变视图时停止?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear( animated)
    meditationState = .on
    setTrackForPlayerWith(trackName: "Bigsur")
    player.play()
    player.numberOfLoops = -1

}

这是 viewcontroller.swift 的全部 class。我已经添加了 func scrollViewDidScroll 和你提到的 self 部分,但它仍然无法正常工作。

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

@IBOutlet weak var scrollView: UIScrollView!

override func viewDidLoad() {
    super.viewDidLoad()

    let vc0 = ViewController0(nibName: "ViewController0", bundle: nil)

    var frame0 = vc0.view.frame
    frame0.origin.x = self.view.frame.size.width
    vc0.view.frame = frame0

    self.addChildViewController(vc0)
    self.scrollView.addSubview(vc0.view)
    vc0.didMove(toParentViewController: self)

    let vc1 = ViewController1(nibName: "ViewController1", bundle: nil)

    var frame1 = vc1.view.frame
    frame1.origin.x = self.view.frame.size.width
    vc1.view.frame = frame1

    self.addChildViewController(vc1)
    self.scrollView.addSubview(vc1.view)
    vc1.didMove(toParentViewController: self)

    let vc2 = ViewController2(nibName: "ViewController2", bundle: nil)

    var frame2 = vc2.view.frame
    frame2.origin.x = self.view.frame.size.width * 2
    vc2.view.frame = frame2

    self.addChildViewController(vc2)
    self.scrollView.addSubview(vc2.view)
    vc2.didMove(toParentViewController: self)

    let vc3 = ViewController3(nibName: "ViewController3", bundle: nil)

    var frame3 = vc3.view.frame
    frame3.origin.x = self.view.frame.size.width * 3
    vc1.view.frame = frame3

    self.addChildViewController(vc3)
    self.scrollView.addSubview(vc3.view)
    vc3.didMove(toParentViewController: self)

    self.scrollView.contentSize = CGSize(width:     Double(self.view.frame.size.width * 4), height: Double(self.view.frame.size.height - 66))

    self.scrollView.delegate = self

  }

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.x > self.view.frame.size.x {
        player.stop()
    }
}

}

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

}

ViewController3,其中声明 'player':

import UIKit
import AVFoundation

enum MeditationState {
    case on
    case off
}

class ViewController3: UIViewController {

    var player:AVAudioPlayer = AVAudioPlayer()
    var player1:AVAudioPlayer = AVAudioPlayer()
    var meditationState: MeditationState?
    var replicatorLayer = CAReplicatorLayer()
    var dot = CALayer()

    func updateTimer(){

        seconds += 1
        timerclock.text = "\(seconds)"
    }

    // Animation starts running

    func animation2() {

        // A layer that creates a specified number of copies of its sublayers (the source layer), each copy potentially having geometric, temporal, and color transformations applied to it.
        replicatorLayer = CAReplicatorLayer()

        // The layer’s bounds rectangle. Animatable.
        replicatorLayer.bounds = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0)

        // The radius to use when drawing rounded corners for the layer’s background. Animatable.
        replicatorLayer.cornerRadius = 10.0

        // The background color of the receiver. Animatable.
        replicatorLayer.backgroundColor = UIColor(white: 0.0, alpha: 0.0).cgColor

        // The layer’s position in its superlayer’s coordinate space. Animatable.
        replicatorLayer.position = view.center

        // calling this method creates an array for that property and adds the specified layer to it.
        view.layer.addSublayer(replicatorLayer)


        // connectng the animation to the content

        // An object that manages image-based content and allows you to perform animations on that content
         dot = CALayer()

        // The layer’s bounds rectangle. Animatable.
        dot.bounds = CGRect(x: 0.0, y: 0.0, width: 12.0, height: 12.0)

        //The layer’s position in its superlayer’s coordinate space. Animatable.
        dot.position = CGPoint(x: 150.0, y: 40.0)

        //The background color of the receiver. Animatable.
        dot.backgroundColor = UIColor(white: 0.2, alpha: 1.0).cgColor

        // The color of the layer’s border. Animatable.
        dot.borderColor = UIColor(white: 1.0, alpha: 1.0).cgColor

        // The width of the layer’s border. Animatable.
        dot.borderWidth = 1.0

        //The radius to use when drawing rounded corners for the layer’s background. Animatable.
        dot.cornerRadius = 5.0


        //Appends the layer to the layer’s list of sublayers.
        replicatorLayer.addSublayer(dot)

        // number of copies of layer is instanceCount

        let nrDots: Int = 1000

        //The number of copies to create, including the source layers.
        replicatorLayer.instanceCount = nrDots

        // The basic type for floating-point scalar values in Core Graphics and related frameworks.
        let angle = CGFloat(2*M_PI) / CGFloat(nrDots)

        // The transform matrix applied to the previous instance to produce the current instance. Animatable.
        replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0.0, 0.0, 1.0)

        // Type used to represent elapsed time in seconds.
        let duration: CFTimeInterval = 10.0

        // animation capabilities for a layer property.

        // An object that provides basic, single-keyframe animation capabilities for a layer property.
        let shrink = CABasicAnimation(keyPath: "transform.scale")

        // Defines the value the receiver uses to start interpolation.
        shrink.fromValue = 1.0

        // Defines the value the receiver uses to end interpolation.
        shrink.toValue = 0.1

        // Specifies the basic duration of the animation, in seconds.
        shrink.duration = duration

        // Determines the number of times the animation will repeat.
        shrink.repeatCount = Float.infinity

        // Add the specified animation object to the layer’s render tree.
        dot.add(shrink, forKey: "shrink")

        // Specifies the delay, in seconds, between replicated copies. Animatable.
        replicatorLayer.instanceDelay = duration/Double(nrDots)

        // The transform applied to the layer’s contents. Animatable.
        dot.transform = CATransform3DMakeScale(0.01, 0.01, 0.01)
    }

    // connecting the breathe in label

    @IBOutlet weak var label: UILabel!

    // instant delay

    @IBOutlet weak var instantDelay: UIButton!
    @IBAction func delayBtn(_ sender: Any) {

        dot.removeAnimation(forKey: "shrink")
        timer1.invalidate()
        seconds = 0
        timer2.invalidate()
        timerclock.text = "\(seconds)"
        time = 0
        timerLabel.text = "Breathe in"
        timerisOn = false
        pauseBtn.isHidden = true
        playBtn.isHidden = false

        label.isHidden = true
        replicatorLayer.isHidden = true
        instantDelay.isHidden = true
        instantDelay1.isHidden = false
        slider.isHidden = false
    }

    // Delay 1

    @IBOutlet weak var instantDelay1: UIButton!
    @IBAction func delayBtn1(_ sender: Any) {


        instantDelay1.isHidden = true
        instantDelay.isHidden = false
        label.isHidden = false
        slider.isHidden = true
    }


    //Slider for changing animation speed

    @IBOutlet weak var slider: UISlider!
    @IBAction func slider(_ sender: Any) {

    }

    @IBAction func speed(_ sender: UISlider) {
        view.layer.speed = sender.value

    }



    //Sound On button

    @IBOutlet weak var soundOn: UIButton!
    @IBAction func SoundOn(_ sender: Any) {
        meditationState = .on
    setTrackForPlayerWith(trackName: "Mute")
        player.play()
        soundoff.isHidden = false
        soundOn.isHidden = true
    }

    //Sound Off button

    @IBOutlet weak var soundoff: UIButton!
    @IBAction func SoundOff(_ sender: Any) {
        meditationState = .off
        setTrackForPlayerWith(trackName: "Bigsur")
        player.play()
        soundoff.isHidden = true
        soundOn.isHidden = false
    }

    //Timerclock at top of screen label

    @IBOutlet weak var timerclock: UILabel!

    // creating vars to set things

    var animation = CFTimeInterval()
    var timer1 = Timer()
    var timer2 = Timer()
    var time = 0
    var seconds = 0
    var timerisOn = false

    // connecting breathe in label

    @IBOutlet var question: UILabel!

    var arrayOfStrings: [String] = [""]

    // connecting timerclick and starting it
    @IBOutlet var timerLabel: UILabel!

    // changes the amount of time on the label of different labels
    func increaseTimer() {

        time += 1

        switch time {
        case 0 ... 7:
            timerLabel.text = "Hold"
        case 8 ... 10:
            timerLabel.text = "Breathe Out"
        case 11 ... 12:
            timerLabel.text = "Breathe in"
        default:
            time = 0
        }

    }

    // connecting the play button and vars
    @IBOutlet weak var playBtn: UIButton!
    @IBAction func play(sender: AnyObject) {

        bell(trackName: "Bell")
        player1.play()

        timer1 = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController3.increaseTimer), userInfo: nil, repeats: true)
        pauseBtn.isHidden = false
        playBtn.isHidden = true
        if timerisOn == false {


        timer2 = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
            timerisOn = true
        }
        animation2()
    }


    // pausing the timer with the vars

    @IBOutlet weak var pauseBtn: UIButton!
    @IBAction func pause(sender: AnyObject) {
        dot.removeAnimation(forKey: "shrink")
        timer1.invalidate()
        seconds = 0
        timer2.invalidate()
        timerclock.text = "\(seconds)"
        time = 0
        timerLabel.text = "Breathe in"
        timerisOn = false
        pauseBtn.isHidden = true
        playBtn.isHidden = false

        }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear( animated)
        meditationState = .on
        setTrackForPlayerWith(trackName: "Bigsur")
        player.play()
        player.numberOfLoops = -1

    }

   override func viewDidLoad() {
        super.viewDidLoad()
    time += 1
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
            print("AVAudioSession Category Playback OK")
            do {
                try AVAudioSession.sharedInstance().setActive(true)
                print("AVAudioSession is Active")
            } catch let error as NSError {
                print(error.localizedDescription)
            }
        } catch let error as NSError {
            print(error.localizedDescription)
        }

    }

        func setTrackForPlayerWith(trackName: String) {
            do
            {
                let audioPath = Bundle.main.path(forResource: trackName, ofType: "mp3")
                try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
            }
            catch
            {
                //ERROR
            }
        }


    func bell(trackName: String) {
        do
        {
            let audioPath = Bundle.main.path(forResource: trackName, ofType: "mp3")
            try player1 = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
        }
        catch
        {
            //ERROR
        }
    }

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



}

您可以在各种委托方法中观察 UIScrollView 子类中所做的更改。

首先,确保您的 scrollView 的委托已分配给 viewController。为此,一种选择是将以下内容添加到 viewDidLoad()

// `scrollView` should be whatever is your scrollView called in your VC
self.scrollView.delegate = self

完成后,让您的 UIViewController 子类符合 UIScrollViewDelegate

class ViewController: UIViewController, UIScrollViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.x > self.view.frame.size.x {
            player.stop()
        }
    }
}

UIScrollViewDelegate 有许多方法可以观察 scrollView 的变化。每次与 scrollView 交互时都会调用 scrollViewDidScroll(_:),所以一旦 contentOffset 大于视图的宽度,就让音乐停止。

您在寻找 viewWillDisappear(_:) 吗?在该方法中,您只需添加 player.stop() 即可在更改视图时停止音乐。

聪明的方法就是....

假设它是垂直的 table。

1. 每个 table 视图单元格都有一个与之关联的音轨。想想一个特定的单元格 - C - 它有一个音轨 A.

2. 随着视图滚动(即,无论何时移动),只需获取C[=10=的帧 ]

3. 就拿身高来说吧。然后取屏幕SH的高度。然后得到 C 到屏幕中心的距离 .. 所以 Abs(SH - H)。然后将该数字作为 SH 的分数(零到一)。所以,Abs(SH - H)/H

(根据您的情况,如果将其除以单元格高度而不是屏幕高度可能会更好。)

4. 现在...只需将所有音轨 A 的 音量设置为那个分数。事实上,只需对每个单元格执行此操作即可。

滚动时,音频将在各个音轨之间混合。

"Magic":)