Replace the system volume popup with a more subtle indicator.

Related tags

Audio SubtleVolume
Overview

CocoaPods Carthage compatible Swift 5.0

Replace the volume popup with a more subtle way to display the volume when the user changes it with the volume rocker.

Why and how

The iOS default popover showing the volume status that appears when the user clicks the volume rocker is a big obtrusive glossy view that covers the content shown. This library offers a way to show a more subtle indicator. To make sure that the popover is not shown there are two conditions that need to be satisfied:

  • An AVAudioSession needs to be active
  • An MPVolumeView needs to be in the current view's hierarchy, and its alpha needs to be greater than 0

Once a SubtleVolume is added to your view, an audio session is automatically started, and the view's alpha is set to 0.0001 in the hidden state.

Getting Started

Create an instance of SubtleVolume with one of its convenience initializers, and set its position (you can either set the frame or let autolayout handle it):

let volume = SubtleVolume(style: .plain)
volume.frame = CGRect(x: 0, y: 10, width: UIScreen.main.bounds.width, height: 4) // or wherever you like

Set the barTintColor property:

volume.barTintColor = .red

Set the animation type if needed (no animation will result in the indicator being always visible):

volume.animation = .slideDown

Add the view to your hierarchy:

view.addSubview(volume)

To change the volume programmatically:

try? volume.setVolumeLevel(0.5)

Or use the convenience methods:

try? volume.decreaseVolume(by: 0.2, animated: true)
try? volume.increaseVolume(by: 0.2, animated: true)

Accessory image

You can provide an accessory image that will be shown to the bar's left. See the delegate method:

func subtleVolume(_ subtleVolume: SubtleVolume, accessoryFor value: Double) -> UIImage? {
  return value > 0 ? #imageLiteral(resourceName: "volume-on.pdf") : #imageLiteral(resourceName: "volume-off.pdf")
}

iPhone X(S/R) support

Want to be fancy and show the volume bar in the notch area? Check out the demo project. The main gist is this:

class ViewController: UIViewController {
  let volume = SubtleVolume(style: .rounded)
  var statusBarVisible = true

  // ...

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if view.safeAreaInsets.top > 0 {
      volume.padding = CGSize(width: 2, height: 8)
      volume.frame = CGRect(x: 16, y: 8, width: 60, height: 20)
    } else {
      // older phones here
    }
  }

  override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
  }

  override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
    return .slide
  }

  override var prefersStatusBarHidden: Bool {
    return !statusBarVisible
  }
}

extension ViewController: SubtleVolumeDelegate {
  func subtleVolume(_ subtleVolume: SubtleVolume, didChange value: Double) {
    if !subtleVolume.isAnimating && view.safeAreaInsets.top > 0 {
      statusBarVisible = true
      UIView.animate(withDuration: 0.1) {
        self.setNeedsStatusBarAppearanceUpdate()
      }
    }
  }

  func subtleVolume(_ subtleVolume: SubtleVolume, willChange value: Double) {
    if !subtleVolume.isAnimating && view.safeAreaInsets.top > 0 {
      statusBarVisible = false
      UIView.animate(withDuration: 0.1) {
        self.setNeedsStatusBarAppearanceUpdate()
      }
    }
  }
}

Handle the background state

Once your app goes in background, you'll need to resume the session when it becomes active:

NotificationCenter.default.addObserver(volume, selector: #selector(SubtleVolume.resume), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)

SubtleVolume automatically removes the observer on deinit.

Hire us

Written by Andrea Mazzini. We're available for freelance work, feel free to contact us here.

Want to support the development of these free libraries? Buy me a coffee ☕️ via Paypal.

MIT License

Copyright (c) 2017-2018 Andrea Mazzini. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Comments
  • Typo in method name. increseVolume -> increaseVolume

    Typo in method name. increseVolume -> increaseVolume

    Found a typo in method name: https://github.com/andreamazz/SubtleVolume/blob/9a6814265d13cfe50771212be5f984b07b95c07a/Source/SubtleVolume.swift#L170

    I guess this would be a breaking change since it’s changing public API.

    opened by jwandrews 3
  • Added ability to change device volume level programatically

    Added ability to change device volume level programatically

    I have exposed the getter for volumeLevel publicly and added a function to change the volume of the device programatically. It includes the option to animate the change or not.

    I have also added the new functionality to the README.

    opened by gapl 3
  • Not showing after webkit view played

    Not showing after webkit view played

    Hi guys,

    After few tried I understood that SubtleVolume is not working if a video has been played through the WebKit view (WKWebView).

    So, for reproduce the issue, load a web page (YouTube), try to increase or decrease the volume (everything is working for what about the SubtleVolume) then play a video, come back and no custom controls anymore.

    opened by PietroMessineo 2
  • iPhone X support with insets, padding, and bring view to front

    iPhone X support with insets, padding, and bring view to front

    safe area insets for iphone x… plus demoing more comfortable and flexible padding… also added a line to bring the volume view to front no matter where it is…

    opened by sevdestruct 2
  • Sample project error

    Sample project error

    The sample project is giving this error when I tap the volume + button.

    Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SubtleVolume.SubtleVolumeError.unableToChangeVolumeLevel

    And this is where it fails-

    @IBAction func plusAction() {
        try! volume.setVolumeLevel(volume.volumeLevel + 0.05, animated: true)
      }
    
    opened by annjawn 2
  • codebeat badge

    codebeat badge

    Is it fine to add codebeat badge to README?

    codebeat is automated code review tool for Swift,Ruby,Go & Python that helps get instant feedback on code quality.

    "Quick wins" suggested by codebeat could be a nice candidate for a pull request and help other developers become contributors.

    FYI. To be fully open and honest. I'm co-founder of codebeat.

    opened by korzonek 2
  • rounded style

    rounded style

    Not sure where to put this in your code, but could you hook this into your .roundedLine enum style?

    overlay.layer.cornerRadius = overlay.frame.height / 2
    volume.layer.cornerRadius = volume.frame.height / 2
    
    opened by sevdestruct 1
  • SubtleVolume Objective-C

    SubtleVolume Objective-C

    Hi there,

    I converted your amazing SubtleVolume Project :+1: to Objective-C and also made it available through CocoaPod (https://github.com/SvenTiigi/STSubtleVolumeC)

    I've used some of your graphics in the readme file. I hope it's okay. If you wish to remove some of the graphics from the readme file just open a issue like I do :)

    Great Work!

    opened by SvenTiigi 1
  • Not removing self as an observer

    Not removing self as an observer

    Basically what it says in the title. Would gladly open a pull request when I have 15 min to breathe :) Otherwise this is the snippet:

    deinit {
        AVAudioSession.sharedInstance().removeObserver(self, forKeyPath: "outputVolume", context: nil)
    }
    
    opened by gapl 1
  • Fix broken headings in Markdown files

    Fix broken headings in Markdown files

    GitHub changed the way Markdown headings are parsed, so this change fixes it.

    See bryant1410/readmesfix for more information.

    Tackles bryant1410/readmesfix#1

    opened by bryant1410 0
  • MPVolume Hud doesn't disappear with AVPlayerViewController

    MPVolume Hud doesn't disappear with AVPlayerViewController

    I have a UIViewController with an AVPlayerViewController in it. I disable MPVolume Hud in the ViewController, and it doesn't appear until I play the AVPlayer in the AVPlayerViewController. I know that with

    avplayercontroller.showsPlaybackControls = false

    the hud disappears, but the problem is that every control disappears, and I need controls, and I prefer to use system controls instead of custom ones.

    SubtleVolume works, but when I play the Player controller both the hud and SubtleVolume are visible.

    I tried to create a MPVolume and add it to the app window, to the player controller view, but the hud is still visible.

    let volumeView = MPVolumeView(frame: CGRect.zero)
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate, let window = appDelegate.window {
        window.insertSubview(volumeView, at: 0)
    }
    

    I've tried almost everything, but I can't figure out what is the problem.

    opened by gianpispi 4
  • Accessory image fix

    Accessory image fix

    When trying to apply an accessory image to the volume bar, I noticed that it wasn't displaying properly. The code was basing the accessory frame on the bar height and since my bar height was quite smaller than the accessory image, that was causing the issue. I updated it so that the image size is used instead.

    opened by gutenbergn 0
  • Crash when trying to manual setVolumeLevel without animated

    Crash when trying to manual setVolumeLevel without animated

    Hi, I was tried to manual setVolumeLevel without animated = false but app crashed.

    *** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <SubtleVolume.SubtleVolume 0x11bc79d80> for the key path "outputVolume" from <AVAudioSession 0x11bc389f0> because it is not registered as an observer.'

    opened by tienphong923 2
Releases(0.5.2)
Owner
Andrea Mazzini
💻 Software Engineer 🌲 Woodworker
Andrea Mazzini
Volume knob for Beoplay speakers

Knob Volume knob for Beoplay speakers. The app communicates with the Beoplay speaker over WiFi. Tested with a Beoplay A6. Features It's really just a

Simon Støvring 9 Jun 27, 2022
Successor of iTunes Volume Control

Volume Control (for Apple Music and Spotify) Description This app allows you to directly control the volume of Apple Music and of Spotify using volume

Andrea Alberti 104 Jan 6, 2023
🖥 Control your display's brightness & volume on your Mac as if it was a native Apple Display

?? Control your display's brightness & volume on your Mac as if it was a native Apple Display. Use Apple Keyboard keys or custom shortcuts. Shows the native macOS OSDs.

null 20k Dec 29, 2022
Cool Animated music indicator view written in Swift

Cool Animated music indicator view written in Swift. ESTMusicIndicator is an implementation of NAKPlaybackIndicatorView in Swift for iOS 8. 本人著作的书籍《La

Aufree 465 Nov 28, 2022
Queue management system for AVSpeechSynthesizer

QHSpeechSynthesizerQueue Queue management system for AVSpeechSynthesizer Installation Cocoapods Add this to your Podfile: pod 'QHSpeechSynthesizerQueu

Quentin Hayot 42 Dec 17, 2021
PTStations - MacOS App to gather the information on the Train Station of the Portuguese Railway system

PTStations A simple macOS app that gathers information on the Portuguese Railway

Joao Pires 2 Aug 10, 2022
An iOS app that visually clones Spotify's app and consumes the official Spotify's Web API to show(and play) songs, podcasts, artists and more.

SpotifyClone An iOS app that visually clones Spotify's app and consumes the official Spotify's Web API to show(and play) songs, podcasts, artists and

null 104 Jan 7, 2023
An animated popover that pops out a given frame, great for subtle UI tips and onboarding.

Animated popover that pops out of a frame. You can specify the direction of the popover and the arrow that points to its origin. Color, border radius

Andrea Mazzini 3k Jan 8, 2023
A SwiftUI List Picker to replace system Picker in List

BetterListPicker An alternative customizable list picker in order to replace built-in non customizable Picker when we write settings view codes. Demo

Jinya 1 Apr 11, 2022
A set of libraries to help users find and replace native system emojis with EmojiOne in their app or website.

This repository is now maintained as JoyPixels/emoji-toolkit. You'll find the latest version of our resources at emoji-toolkit. Please see the UPGRADE

JoyPixels Inc. 4.5k Dec 24, 2022
Floating indicator, mimicrate to indicator which appear when silent mode turn on / off. Support large texts.

SPIndicator About Mimicrate to indicator which appear when silent mode turn on / off. Availalbe 2 animated presets: done & error. Also support custom

Ivan Vorobei 568 Dec 30, 2022
Recording Indicator Utility lets you turn off the orange microphone recording indicator light for live events and screencasts.

Recording Indicator Utility Recording Indicator Utility lets you turn off the orange microphone recording indicator light, making it ideal for profess

Tyshawn Cormier 121 Jan 1, 2023
A Swift Popup Module help you popup your custom view easily

JFPopup JFPopup is a Swift Module help you popup your custom view easily. Support 3 way to popup, Drawer, Dialog and BottomSheet. Example To run the e

逸风 77 Dec 14, 2022
CHIPageControl is a set of cool animated page controls to replace boring UIPageControl.

CHIPageControl is a set of cool animated page controls to replace boring UIPageControl. We were inspired by Jardson Almeida dribbble sh

Chili Labs 3.1k Jan 4, 2023
Replace your Xcode icon with colorful variants

XcoatOfPaint Have you ever wished the Xcode icon could get a fresh coat of paint to match the colorful Mac you just bought? Or you want to distinguish

Christian Lobach 163 Dec 20, 2022
Jogendra 113 Nov 28, 2022
This is a selection of custom page controls to replace UIPageControl

PageControls This is a selection of custom page controls to replace UIPageControl, inspired by a dribbble found here. The appearance (color, size, # o

Kyle Zaragoza 1k Jan 2, 2023
A Swift based reimplementation of the Apple HUD (Volume, Ringer, Rotation,…) for iOS 8.

A Swift based reimplementation of the Apple HUD (Volume, Ringer, Rotation,…) for iOS 8 and up. Features Official iOS 8 blur effect via UIVisualEffects

Philip Kluz 3.7k Jan 9, 2023
🕳 A simple command line tool to punch hole to reduce disk usage on APFS volume for such as a raw disk image.

HolePunch NAME holepunch -- A simple command line tool to punch hole to reduce disk usage on APFS volume for such as a raw disk image. SYNOPSIS holepu

Yoshimasa Niwa 15 Nov 24, 2022
Volume knob for Beoplay speakers

Knob Volume knob for Beoplay speakers. The app communicates with the Beoplay speaker over WiFi. Tested with a Beoplay A6. Features It's really just a

Simon Støvring 9 Jun 27, 2022