Skip to content

Instantly share code, notes, and snippets.

@chunkyguy
Created December 7, 2017 18:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chunkyguy/77c9ffaa4536adc67caf089669891e56 to your computer and use it in GitHub Desktop.
Save chunkyguy/77c9ffaa4536adc67caf089669891e56 to your computer and use it in GitHub Desktop.
//
// ViewController.swift
// KeyboardTransitionBug
//
// Created by Sid on 07/12/2017.
// Copyright © 2017 Picnic. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet var imageView: UIImageView!
@IBOutlet var searchField: SearchHeaderView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(onShowingKeyboard(notif:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
}
@objc func onShowingKeyboard(notif: Notification) {
addAndAnimate(parentView: imageView, info: notif.userInfo)
}
@IBAction func onTap() {
addAndAnimate(parentView: imageView, info: nil)
}
func addAndAnimate(parentView: UIView, info: [AnyHashable : Any]?) {
let (containerView, contentView, frame, constraints) = add(parentView: parentView)
DispatchQueue.main.async { [weak self] in
self?.animate(containerView: containerView, contentView: contentView, frame: frame, constraints: constraints, info: info)
}
}
func add(parentView: UIView) -> (UIView?, UIView, CGRect, [NSLayoutConstraint]) {
let img = UIImageView(image: UIImage(named: "IMG_4389.JPG"))
let coordinateSpace = UIScreen.main.fixedCoordinateSpace
let frame = view.convert(parentView.frame, to: coordinateSpace)
let superView = UIApplication.shared.keyWindow?.rootViewController?.view //UIApplication.shared.keyWindow
superView?.addSubview(img)
img.translatesAutoresizingMaskIntoConstraints = false
let constraints: [NSLayoutConstraint] = [
NSLayoutConstraint(item: img, attribute: .left, relatedBy: .equal, toItem: superView, attribute: .left, multiplier: 1.0, constant: frame.origin.x),
NSLayoutConstraint(item: img, attribute: .top, relatedBy: .equal, toItem: superView, attribute: .top, multiplier: 1.0, constant: frame.origin.y),
NSLayoutConstraint(item: img, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: frame.size.width),
NSLayoutConstraint(item: img, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: frame.size.height)
]
superView?.addConstraints(constraints)
return (superView, img, frame, constraints)
}
func animate(containerView: UIView?, contentView: UIView, frame: CGRect, constraints: [NSLayoutConstraint], info: [AnyHashable : Any]?) {
precondition(containerView != nil)
precondition(contentView.superview != nil)
precondition(contentView.superview == containerView)
precondition(constraints.count == 4)
let duration: Double = (info?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 3.0
let animationCurveRawNSN = info?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = Int(animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue)
let animationCurve = UIViewAnimationCurve(rawValue: animationCurveRaw) ?? UIViewAnimationCurve.easeOut
let finalFrame = CGRect(x: frame.origin.x + 100, y: frame.origin.y - 100, width: 100, height: 100)
print("\(frame) -> \(finalFrame)")
containerView?.layoutIfNeeded()
UIView.beginAnimations("animation-007", context: nil)
UIView.setAnimationDuration(duration)
UIView.setAnimationCurve(animationCurve)
UIView.setAnimationBeginsFromCurrentState(true)
constraints[0].constant = finalFrame.origin.x
constraints[1].constant = finalFrame.origin.y
constraints[2].constant = finalFrame.size.width
constraints[3].constant = finalFrame.size.height
containerView?.layoutIfNeeded()
UIView.commitAnimations()
// UIView.animate(withDuration: 3.0, delay: 0.0, options: [], animations: { [weak containerView] in
// constraints[0].constant = finalFrame.origin.x
// constraints[1].constant = finalFrame.origin.y
// constraints[2].constant = finalFrame.size.width
// constraints[3].constant = finalFrame.size.height
// containerView?.layoutIfNeeded()
// }, completion: { [weak contentView] complete in
// assert(complete)
// contentView?.removeFromSuperview()
// })
}
@IBAction func onDismiss() {
searchField.dismissKeyboard()
}
}
final class SearchHeaderView: UIView {
/// The title for the toggle button
var toggleButtonTitle: String? {
get {
return toggleButton.title(for: .normal)
}
set {
toggleButton.setTitle(newValue, for: .normal)
}
}
/// The image for the toggle button
var toggleButtonImage: UIImage? {
get {
return toggleButton.image(for: .normal)
}
set {
toggleButton.setImage(newValue, for: .normal)
}
}
// MARK: - UI Elements
private let searchBar = UISearchBar()
private let toggleButton = UIButton()
init(barcodeScannerEnabled: Bool) {
super.init(frame: .zero)
setUp(displayBarcodeScannerButton: barcodeScannerEnabled)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp(displayBarcodeScannerButton: false)
}
override init(frame: CGRect) {
super.init(frame: frame)
setUp(displayBarcodeScannerButton: false)
}
private func setUp(displayBarcodeScannerButton: Bool) {
/* Set the color of search bar background */
// switch searchBarStyle
// case .Prominent: inner view is automatically set to white, with a default 1px black border
// case .Minimal: inner view is automatically set to some darker shade of background color
let searchBackgroundColor = UIColor.lightGray
/* color for elements within search bar like: text, input flashing indicator */
backgroundColor = searchBackgroundColor
/* add search bar */
addSubview(searchBar)
/* configure search bar */
searchBar.searchBarStyle = .prominent
searchBar.isTranslucent = false
searchBar.barTintColor = searchBackgroundColor
searchBar.tintColor = UIColor.red
searchBar.autocapitalizationType = .none
searchBar.backgroundImage = UIImage() // get rid of 1px black line
/* add button */
if displayBarcodeScannerButton {
addSubview(toggleButton)
/* configure button */
toggleButton.setTitleColor(UIColor.red, for: .normal)
toggleButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body)
}
/* add constraints */
searchBar.translatesAutoresizingMaskIntoConstraints = false
addConstraints([
NSLayoutConstraint(item: searchBar, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 8.0),
NSLayoutConstraint(item: searchBar, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 8.0),
NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: searchBar, attribute: .bottom, multiplier: 1.0, constant: 8.0),
])
if displayBarcodeScannerButton {
toggleButton.translatesAutoresizingMaskIntoConstraints = false
addConstraints([
NSLayoutConstraint(item: toggleButton, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: -16.0),
NSLayoutConstraint(item: toggleButton, attribute: .centerY, relatedBy: .equal, toItem: searchBar, attribute: .centerY, multiplier: 1.0, constant: 0.0),
NSLayoutConstraint(item: toggleButton, attribute: .leading, relatedBy: .equal, toItem: searchBar, attribute: .trailing, multiplier: 1.0, constant: 8.0)
])
} else {
addConstraints([
NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal, toItem: searchBar, attribute: .trailing, multiplier: 1.0, constant: 8.0),
])
}
isAccessibilityElement = false
}
func presentKeyboard() {
searchBar.becomeFirstResponder()
}
func dismissKeyboard() {
searchBar.resignFirstResponder()
}
func setQuery(query: String) {
searchBar.text = query
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment