Skip to content

Instantly share code, notes, and snippets.

View RaajeevChandran's full-sized avatar

Raajeev Chandran RaajeevChandran

View GitHub Profile
class StreamingLabel: UILabel {
weak var delegate: StreamingLabelDelegate?
private var streamDelay: TimeInterval = 0.05
private var targetText: String = ""
private var currentIndex: String.Index?
private var displayTimer: Timer?
var charactersPerSecond: Float {
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .system)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("Show Sheet", for: .normal)
btn.addTarget(self, action: #selector(tap), for: .touchUpInside)
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .system)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("Show Sheet", for: .normal)
btn.addTarget(self, action: #selector(tap), for: .touchUpInside)
view.addSubview(btn)
NSLayoutConstraint.activate([
import UIKit
class BottomSheetPresentationController: UIPresentationController {
private let dismissThreshold: CGFloat = 0.3
private let grabberView: UIView = {
let view = UIView()
view.frame.size = CGSize(width: 50, height: 3)
view.backgroundColor = .lightGray
private func didInteractionEnd() {
guard let presentedView = presentedView else {
return
}
if let transitioningDelegate = transitioningDelegate {
let dismissFraction = transitioningDelegate.transition.dismissFractionComplete
if dismissFraction > dismissThreshold {
transitioningDelegate.transition.finish()
private func didGestureTranslationChange(_ translation: CGPoint) {
guard let presentedView = presentedView else {
return
}
let translationY = max(0, translation.y)
presentedView.transform = CGAffineTransform(translationX: 0, y: translationY)
let progress = translationY / presentedView.frame.height
transitioningDelegate?.transition.update(progress)
@objc private func pannedPresentedView(_ recognizer: UIPanGestureRecognizer) {
guard let presentedView = presentedView else {
return
}
switch recognizer.state {
case .began:
transitioningDelegate?.transition.wantsInteractiveStart = true
case .changed:
private func dismiss(withInteraction: Bool) {
transitioningDelegate?.transition.wantsInteractiveStart = withInteraction
presentedViewController.dismiss(animated: true)
}
extension BottomSheetPresentationController {
private func setupInteraction() {
guard let presentedView = presentedView else {
return
}
func addGestureIfNeeded(_ gesture: UIGestureRecognizer, to view: UIView, delegate: UIGestureRecognizerDelegate? = nil) {
if let recognizers = view.gestureRecognizers, recognizers.contains(gesture) {
return
}
override func dismissalTransitionWillBegin() {
super.dismissalTransitionWillBegin()
presentedViewController.transitionCoordinator?.animate(alongsideTransition: { [weak self] _ in
guard let self else { return }
self.presentedView?.layer.cornerRadius = .zero
self.dimmedBackgroundView.backgroundColor = .clear
})
}