create a box that if tapped it plays a sound, long press it to display a volume slider to change its volume, use swiftui in swift in swift

To create a box that plays a sound upon tap and shows a volume slider upon long press, follow these steps:

  1. Create a new SwiftUI view and import AVFoundation framework:
main.swift
import SwiftUI
import AVFoundation
35 chars
3 lines
  1. Define a state variable to hold the current volume of the sound:
main.swift
@State private var volumeValue: Float = 0.5
44 chars
2 lines
  1. Create an AVAudioPlayer object and load the sound file into it:
main.swift
private var soundPlayer: AVAudioPlayer?

init() {
    guard let soundURL = Bundle.main.url(forResource: "sound", withExtension: "mp3") else { return }
    do {
        soundPlayer = try AVAudioPlayer(contentsOf: soundURL)
        soundPlayer?.prepareToPlay()
    } catch {
        print("Failed to load sound file.")
    }
}
325 chars
12 lines
  1. Create a Gesture modifier to handle tap and long press gestures:
main.swift
struct SoundBox: View {
    
    private let longPressDuration = 0.5

    var body: some View {
        RoundedRectangle(cornerRadius: 10)
            .fill(Color.blue)
            .frame(width: 100, height: 100)
            .onTapGesture {
                self.playSound()
            }
            .simultaneousGesture(longPressGesture)
    }
    
    private var longPressGesture: some Gesture {
        LongPressGesture(minimumDuration: longPressDuration)
            .onChanged { _ in
                isChangingVolume = true
            }
            .onEnded { _ in
                isChangingVolume = false
            }
    }
    
    private func playSound() {
        soundPlayer?.stop()
        soundPlayer?.currentTime = 0
        soundPlayer?.play()
    }
}
770 chars
31 lines
  1. Define a boolean state variable to track whether the volume slider is currently being displayed:
main.swift
@State private var isChangingVolume = false
44 chars
2 lines
  1. Add a ZStack to display the volume slider only when isChangingVolume is true:
main.swift
var body: some View {
    ZStack {
        RoundedRectangle(cornerRadius: 10)
            .fill(Color.blue)
            .frame(width: 100, height: 100)
            .onTapGesture {
                self.playSound()
            }
        
        if isChangingVolume {
            Slider(value: $volumeValue, in: 0...1)
                .padding()
                .background(Color.white)
                .cornerRadius(10)
                .shadow(radius: 10)
        }
    }
    .simultaneousGesture(longPressGesture)
}
516 chars
20 lines

The final SoundBox struct should look something like this:

main.swift
struct SoundBox: View {
    
    @State private var volumeValue: Float = 0.5
    @State private var isChangingVolume = false
    
    private let longPressDuration = 0.5
    private var soundPlayer: AVAudioPlayer?

    init() {
        guard let soundURL = Bundle.main.url(forResource: "sound", withExtension: "mp3") else { return }
        do {
            soundPlayer = try AVAudioPlayer(contentsOf: soundURL)
            soundPlayer?.prepareToPlay()
        } catch {
            print("Failed to load sound file.")
        }
    }
    
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.blue)
                .frame(width: 100, height: 100)
                .onTapGesture {
                    self.playSound()
                }
            
            if isChangingVolume {
                Slider(value: $volumeValue, in: 0...1)
                    .padding()
                    .background(Color.white)
                    .cornerRadius(10)
                    .shadow(radius: 10)
            }
        }
        .simultaneousGesture(longPressGesture)
    }
    
    private var longPressGesture: some Gesture {
        LongPressGesture(minimumDuration: longPressDuration)
            .onChanged { _ in
                isChangingVolume = true
            }
            .onEnded { _ in
                isChangingVolume = false
            }
    }
    
    private func playSound() {
        soundPlayer?.stop()
        soundPlayer?.currentTime = 0
        soundPlayer?.volume = volumeValue
        soundPlayer?.play()
    }
}
1599 chars
56 lines

gistlibby LogSnag