SpriteKit Floating Bubble Picker (inspired by Apple Music) 🧲

Overview

Magnetic

Build Status Language Version License Platform Carthage compatible

Magnetic is a customizable bubble picker like the Apple Music genre selection.

Demo GIF

Demo Video

$ pod try Magnetic

Features

  • Adding/Removing Nodes
  • Selection/Deselection/Removed Animations
  • Multiple Selection
  • Images
  • Multiline Label
  • Documentation

Requirements

  • iOS 9.0+
  • Xcode 9.0+
  • Swift 5 (Magnetic 3.x), Swift 4 (Magnetic 2.x), Swift 3 (Magnetic 1.x)

Usage

A Magnetic object is an SKScene.

To display, you present it from an SKView object.

import Magnetic

class ViewController: UIViewController {

    var magnetic: Magnetic?
    
    override func loadView() {
        super.loadView()
        
        let magneticView = MagneticView(frame: self.view.bounds)
        magnetic = magneticView.magnetic
        self.view.addSubview(magneticView)
    }

}

Properties

var magneticDelegate: MagneticDelegate? // magnetic delegate
var allowsMultipleSelection: Bool // controls whether you can select multiple nodes. defaults to true
var selectedChildren: [Node] // returns selected chidren

Nodes

A Node object is a SKShapeNode subclass.

Interaction

// add circular node
let node = Node(text: "Italy", image: UIImage(named: "italy"), color: .red, radius: 30)
magnetic.addChild(node)

// add custom node
let node = Node(text: "France", image: UIImage(named: "france"), color: .blue, path: path, marginScale: 1.1)
magnetic.addChild(node)

// remove node
node.removeFromParent()

Properties

var text: String? // node text
var image: UIImage? // node image
var color: UIColor // node color

Animations

override func selectedAnimation() {
    // override selected animation
}

override func deselectedAnimation() {
    // override deselected animation
}

override func removedAnimation(completion: @escaping () -> Void) {
    // override removed animation
}

Delegation

The MagneticDelegate protocol provides a number of functions for observing the current state of nodes.

func magnetic(_ magnetic: Magnetic, didSelect node: Node) {
    // handle node selection
}

func magnetic(_ magnetic: Magnetic, didDeselect node: Node) {
    // handle node deselection
}

Customization

Subclass the Node for customization.

For example, a node with an image by default:

class ImageNode: Node {
    override var image: UIImage? {
        didSet {
            texture = image.map { SKTexture(image: $0) }
        }
    }
    override func selectedAnimation() {}
    override func deselectedAnimation() {}
}

Installation

CocoaPods

To install with CocoaPods, simply add this in your Podfile:

use_frameworks!
pod "Magnetic"

Carthage

To install with Carthage, simply add this in your Cartfile:

github "efremidze/Magnetic"

Mentions

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Credits

https://github.com/igalata/Bubble-Picker

License

Magnetic is available under the MIT license. See the LICENSE file for more info.

Comments
  • Selection

    Selection

    @efremidze First of all great project. But I have one problem. How could I change it so that when one bubble is pressed I can present a new view depending on the index.

    opened by Ahmedshubber 17
  • Image is stretched

    Image is stretched

    New Issue Checklist

    Issue Description

    Image is shown in incorrect ratio. Probably should be aspect fill.

    Environment

    • iOS Version: 11
    • Device(s): All
    opened by alexandre-g 12
  • Problem with name didSelected

    Problem with name didSelected

    I have a problem when I select one bubble. It doesn't recognize the name of the Node. Please help me, thanks

    LOG

    didSelect -> name:'(null)' accumulatedFrame:{{89.760002136230469, 424.89700317382812}, {147, 83}}

    opened by alepiz 5
  • Text Position in Node

    Text Position in Node

    Hi, I am kind of new at swift and I am using your Magnetic pod, however I am building and app that needs the text of the bubbles in the bottom of the bubble. Trying to do so I looked at your files but I only saw that the Y position is managed by a verticaltextalignment that can only be top, bottom, baseline and center, all of this options take the node origin as reference, I would appreciate if you could help me to set the text, in the lower position possible (higher Y position possible in the Node) Thanks very much and sorry if my English is bad. Thank you.

    opened by abraham28s 5
  • How can I customize it to have Image by default?

    How can I customize it to have Image by default?

    I would like to customize it so that the image is shown by default. Also the label for text is not necessary for my use. And I also need to customize what happens when you tap on it.

    Any guidance would be great.

    opened by talkaboutdesign 5
  • How to move to activity when specific Node is clicked?

    How to move to activity when specific Node is clicked?

    Hello! I have a problem. I'm new to iOS development. I've seen issues 1 and 2, but didn't find any solution to my problem. I want to go to next specific activity after each of nodes is clicked. For instance, if you press node1 you go to Activity22, if you press node2 you go to Activity23 and so on... Could you please help me to solve this issue?

    opened by nurlan-dzhavadov 4
  • Accessibility/VoiceOver usability improvements

    Accessibility/VoiceOver usability improvements

    Checklist

    • [x] I've tested my changes.
    • [x] I've read the Contribution Guidelines.
    • [x] I've updated the documentation if necessary.

    Motivation and Context

    Thanks for the delightful library! In preparing for a user test, I noticed a few minor usability issues with VoiceOver(VO):

    • MultiLineLabels are read as individual label elements as opposed to a single label
    • Selection state of a node isn't presented to a VO user
    • There is no easy way for a VO user to quickly confirm selections, which is a benefit of this library for a non-VO user

    Description

    To address the above 3 issues, I have made the following changes

    • Made Node.swift class set accessibilityElement to true (overriding it's children's accessibility settings), as well as enabled the property to group it's children. This allows multiline labels to be read as one, if the nodes accessibilityLabel is not set, but that's set as well. Additionally, this PR adds an accessibilityPath that is, by default computed to be an ellipse inside the sprite shape, but can be overridden or removed if subclassed.
    • Added accessibilityTraits to be selected when a Node is tapped, i.e in the isSelected property.
    • For iOS 10.0 and above, MagneticView.swift is initialized with a "Selected" custom rotor, using accessibilityCustomRotors.
    • Note that for iOS 11.0, the entire Magnetic.swift scene has the added property accessibilityContainerType to be .list. This lets a VO user know when they are entering and leaving the list of items

    I wasn't entirely sure if OS specific code is allowed in this library, but given that this makes tangible benefits to a VO user, I'm hoping it's alright. Tested on Xcode 9.4 and iOS 11.4 betas.

    Happy to make changes as needed!

    opened by mathewa6 4
  • If I want to show few selected and few not selected bubbles, how to show?

    If I want to show few selected and few not selected bubbles, how to show?

    Thanks for great library.

    But, here, I want to show while loading SKView few bubbles are already selected and few are not selected same time.

    How can I achieve this, Can you guide us. Thanks!

    opened by AnilkumarRabhasa 4
  • While scrolling them, the bubbles are completely went out of screen

    While scrolling them, the bubbles are completely went out of screen

    Thanks for the great library. Its helped us. But, while scrolling them horizontally, they are going out from screen and coming back, I want to control this, I just want to scroll, but, should not go out of screen.

    Where can I handle this? Can you help us?

    opened by AnilkumarRabhasa 4
  • Can't set background color to UIColor.clear.

    Can't set background color to UIColor.clear.

    Hi sir,

    thanks for this fancy library first! But I got a problem why I tried to set the background color of magnetic to UIColor.clear, it will return me a black color. This will block the background image, could anyone advise how to address this problem?

    ` @IBOutlet weak var magneticView: MagneticView! {

        didSet {
    
            magnetic.magneticDelegate = self
    
        }
    
    }
    
    var magnetic: Magnetic {
    
        return magneticView.magnetic
    
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        magnetic.allowsMultipleSelection = false
    
        magnetic.backgroundColor = UIColor.clear
    
    }
    

    `

    opened by nick1ee 4
  • Nodes position off-screen

    Nodes position off-screen

    Hi,

    I'm using the Magnetic view as a background view of a collection view when there are no results. Kind of like a suggestion view. I created a separate nib file and added a UIView as a subview for MagneticView.

    import UIKit
    import SpriteKit
    import Magnetic
    
    class SuggestionsView: UIView {
    
        @IBOutlet var view: UIView!
        @IBOutlet weak var magneticView: MagneticView!
        
        var magnetic: Magnetic {
            return magneticView.magnetic
        }
        
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        
        fileprivate func commonInit() {
            Bundle.main.loadNibNamed("SuggestionsView", owner: self, options: nil)
            addSubview(view)
            
            addBubbles()
            magnetic.magneticDelegate = self
        }
        
        fileprivate func addBubbles() {
            let node1 = Node(text: "Eggs", image: UIImage(imageLiteralResourceName: "egg"), color: .gray, radius: 40)
            let node2 = Node(text: "Bread", image: UIImage(imageLiteralResourceName: "bread"), color: .gray, radius: 40)
            let node3 = Node(text: "Meat", image: UIImage(imageLiteralResourceName: "meat"), color: .gray, radius: 40)
            let node4 = Node(text: "Cheese", image: UIImage(imageLiteralResourceName: "cheese"), color: .gray, radius: 40)
            let node5 = Node(text: "Fruits", image: UIImage(imageLiteralResourceName: "fruits"), color: .gray, radius: 40)
            let nodes = [node1, node2, node3, node4, node5]
            
            nodes.forEach { node in
                magnetic.addChild(node)
            }
        }
    }
    
    // MARK: - MagneticDelegate
    extension SuggestionsView: MagneticDelegate {
        func magnetic(_ magnetic: Magnetic, didSelect node: Node) {
            print(node.text)
        }
        
        func magnetic(_ magnetic: Magnetic, didDeselect node: Node) {
            
        }
    }
    

    I'm instantiating the view like this in the view controller.

    collectionView?.backgroundView = SuggestionsView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height))
    

    I'm adding 5 bubbles but some of them always appear off-screen like this.

    rsz_img_4115

    Can't figure out why. I'm using the same value you have in your example project, 40 as the radius. But the bubbles appear bigger too.

    I also created a demo and uploaded it here.

    opened by Isuru-Nanayakkara 4
  • Magnetic view in tableview cell slows down tabbar selection

    Magnetic view in tableview cell slows down tabbar selection

    I have a magneticview inside tableview cell. When i first tap on tab bar item it's fine, but every other time when everything is already loaded it takes up to 2 seconds for tabbar to switch between controllers.

    Environment

    • iOS Version: 15
    • Device(s): [iPhone 12 Pro Max]
    opened by mihaelrek 0
  • Bubble Border issue on Test-flight or Ad-hoc

    Bubble Border issue on Test-flight or Ad-hoc

    The border of bubbles appears when we are testing it manually on the device, but somehow it’s not working after app distribution (test-flight or Ad hoc) image-20220309-060040

    https://user-images.githubusercontent.com/31612250/157402540-b20eff6d-8a86-4bd6-a27d-8eeac939526c.mp4

    https://user-images.githubusercontent.com/31612250/157402558-8afcd6cd-3473-452f-ac8f-fe12e8740afa.mov

    .

    opened by Dev-iOS-Appbirds 0
  • make bubbles motionless

    make bubbles motionless

    Hi,

    I'm wondering if it is possible to make bubbles motionless..? I just want the bubble views to appear at the center of the screen and I want them to stand still.

    If I use set magneticField.isEnabled property to false, bubbles are far from each other, how to make them stick together without magnetic field ?

    Also, magneticField.animationSpeed = 0.0 does nothing.

    I should stil be able to move them around but I want to remove all physic effects.

    Thanks in advance for your help!

    opened by pbeneteau 1
  • How to do bubble are moving in slower rate?

    How to do bubble are moving in slower rate?

    I want to move the all bubbles very slow to bottom & continuously. And do't want to go offscreen & (left, right). how to disable the draggable option?

    opened by harifsp 0
  • How to use it in SwiftUI

    How to use it in SwiftUI

    I'm new to Swift and SwiftUI but did try using UIViewRepresentable but not getting anywhere. Any support helps :)

    P.S. Sorry to use issue to ask a question

    help wanted 
    opened by newbie-swift 4
Owner
Lasha Efremidze
#iOS Engineer @amzn @EdisonJunior (Ring). Previously @eBay @stubhub @calaborate (Klutch). Open source enthusiast.
Lasha Efremidze
A modern HUD inspired by Apple Music and Apple Podcasts

HUD A modern HUD inspired by Apple Music and Apple Podcasts. Appearance Light Dark HUD Activity Indicator HUD Requirements iOS 13+ Installation You ca

Bei Li 30 Nov 18, 2022
:octocat:💧 A slider widget with a popup bubble displaying the precise value selected. Swift UI library made by @Ramotion

FLUID SLIDER A slider widget with a popup bubble displaying the precise value selected written on Swift. We specialize in the designing and coding of

Ramotion 1.9k Dec 23, 2022
A library to recreate the iOS Apple Music now playing transition

DeckTransition DeckTransition is an attempt to recreate the card-like transition found in the iOS 10 Apple Music and iMessage apps. Hereʼs a GIF showi

Harshil Shah 2.2k Dec 15, 2022
Whole, half or floating point ratings control written in Swift

FloatRatingView A simple rating view for iOS written in Swift! Supports whole, half or floating point values. I couldn't find anything that easily set

Glen Yi 546 Dec 8, 2022
Play BreakOut while loading - A playable pull to refresh view using SpriteKit

BreakOutToRefresh Play BreakOut while loading - A playable pull to refresh view using SpriteKit BreakOutToRefresh uses SpriteKit to add a playable min

Dominik Hauser 2.5k Jan 5, 2023
Iridescent Effect View (inspired by Apple Pay Cash) ✨

Shiny Shiny is an iOS library that generates an iridescent effect view matched to the gyroscope, similar to the Apple Pay Cash card in the Wallet app.

Lasha Efremidze 768 Dec 2, 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
A customizable color picker for iOS in Swift

IGColorPicker is a fantastic color picker ?? written in Swift. Table of Contents Documentation Colors Style Other features Installation Example Gettin

iGenius 272 Dec 17, 2022
An iOS picker view to serve all your "picking" needs

Mandoline The PickerView is a UICollectionView that provides a smooth "picking" interface. In order to get the most out of it, a consuming view contro

Blue Apron 883 Nov 28, 2022
Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift

SKPhotoBrowser Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift features Display one or more images by providi

keishi suzuki 2.4k Jan 6, 2023
A micro UIStackView convenience API inspired by SwiftUI

Stacks A micro UIStackView convenience API inspired by SwiftUI. let stack: UIView = .hStack(alignment: .center, margins: .all(16), [ .vStack(spaci

Alexander Grebenyuk 74 Jul 27, 2022
SwiftUI: Components Library Inspired by Twitter's Bootstrap

bootswiftui SwiftUI: Components Library Inspired by Twitter's Bootstrap Warning This is just SwiftUI exercise. Please do not consider using this repo

Robert Sandru 1 Oct 27, 2022
A spotlight-inspired quick action bar for macOS.

DSFQuickActionBar A spotlight-inspired quick action bar for macOS. Why? I've seen this in other mac applications (particularly spotlight) and it's ver

Darren Ford 31 Dec 14, 2022
MUDownloadButton - a Progressive Download button written in pure swift and inspired by AppStore download button

MUDownloadButton is a Progressive Download button written in pure swift and inspired by AppStore download button . feel free to contribute and pull requests

Mohammad ShahibZadeh 2 Feb 20, 2022
UI Component. This is a copy swipe-panel from app: Apple Maps, Stocks. Swift version

ContainerController UI Component. This is a copy swipe-panel from app: https://www.apple.com/ios/maps/ Preview Requirements Installation CocoaPods Swi

Rustam 419 Dec 12, 2022
Kit for building custom gauges + easy reproducible Apple's style ring gauges.

GaugeKit ##Kit for building custom gauges + easy reproducible Apple's style ring gauges. -> Example Usage Open GaugeKit.xcworkspace and change the sch

Petr Korolev 1k Dec 23, 2022
A fancy hexagonal layout for displaying data like your Apple Watch

Hexacon is a new way to display content in your app like the Apple Watch SpringBoard Highly inspired by the work of lmmenge. Special thanks to zenly f

Gautier Gédoux 340 Dec 4, 2022
Apple TV Parallax effect in Swift.

MPParallaxView Apple TV Parallax effect in Swift. Rotate view using touch or accelerometer. Usage To run the example project, clone the repo, and run

Droids On Roids 1.7k Jan 4, 2023