Last active
February 27, 2024 11:21
-
-
Save mayoff/ea37ee75a87efab5d7e8 to your computer and use it in GitHub Desktop.
Revisions
-
mayoff renamed this gist
Mar 6, 2017 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
mayoff created this gist
Jan 17, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,118 @@ import UIKit class FloatingButtonController: UIViewController { private(set) var button: UIButton! required init?(coder aDecoder: NSCoder) { fatalError() } init() { super.init(nibName: nil, bundle: nil) window.windowLevel = CGFloat.max window.hidden = false window.rootViewController = self NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardDidShow:", name: UIKeyboardDidShowNotification, object: nil) } private let window = FloatingButtonWindow() override func loadView() { let view = UIView() let button = UIButton(type: .Custom) button.setTitle("Floating", forState: .Normal) button.setTitleColor(UIColor.greenColor(), forState: .Normal) button.backgroundColor = UIColor.whiteColor() button.layer.shadowColor = UIColor.blackColor().CGColor button.layer.shadowRadius = 3 button.layer.shadowOpacity = 0.8 button.layer.shadowOffset = CGSize.zero button.sizeToFit() button.frame = CGRect(origin: CGPointMake(10, 10), size: button.bounds.size) button.autoresizingMask = [] view.addSubview(button) self.view = view self.button = button window.button = button let panner = UIPanGestureRecognizer(target: self, action: "panDidFire:") button.addGestureRecognizer(panner) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() snapButtonToSocket() } func panDidFire(panner: UIPanGestureRecognizer) { let offset = panner.translationInView(view) panner.setTranslation(CGPoint.zero, inView: view) var center = button.center center.x += offset.x center.y += offset.y button.center = center if panner.state == .Ended || panner.state == .Cancelled { UIView.animateWithDuration(0.3) { self.snapButtonToSocket() } } } func keyboardDidShow(note: NSNotification) { window.windowLevel = 0 window.windowLevel = CGFloat.max } private func snapButtonToSocket() { var bestSocket = CGPoint.zero var distanceToBestSocket = CGFloat.infinity let center = button.center for socket in sockets { let distance = hypot(center.x - socket.x, center.y - socket.y) if distance < distanceToBestSocket { distanceToBestSocket = distance bestSocket = socket } } button.center = bestSocket } private var sockets: [CGPoint] { let buttonSize = button.bounds.size let rect = view.bounds.insetBy(dx: 4 + buttonSize.width / 2, dy: 4 + buttonSize.height / 2) let sockets: [CGPoint] = [ CGPointMake(rect.minX, rect.minY), CGPointMake(rect.minX, rect.maxY), CGPointMake(rect.maxX, rect.minY), CGPointMake(rect.maxX, rect.maxY), CGPointMake(rect.midX, rect.midY) ] return sockets } } private class FloatingButtonWindow: UIWindow { var button: UIButton? init() { super.init(frame: UIScreen.mainScreen().bounds) backgroundColor = nil } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { guard let button = button else { return false } let buttonPoint = convertPoint(point, toView: button) return button.pointInside(buttonPoint, withEvent: event) } }