Top Related Projects
Reactive Programming in Swift
Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.
A Swift binding framework
Network abstraction layer written in Swift.
A library for reactive and unidirectional Swift applications
UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...)
Quick Overview
RxKeyboard is a reactive extension for keyboard events in iOS applications using RxSwift. It provides a convenient way to handle keyboard appearance and disappearance, as well as keyboard frame changes, in a reactive programming style.
Pros
- Simplifies keyboard event handling with reactive programming
- Provides easy access to keyboard frame and animation duration
- Integrates seamlessly with RxSwift and RxCocoa
- Supports both UIKit and SwiftUI
Cons
- Requires knowledge of RxSwift and reactive programming concepts
- May introduce additional complexity for simple keyboard handling scenarios
- Dependency on RxSwift might increase app size
- Limited documentation and examples available
Code Examples
- Observing keyboard frame changes:
import RxKeyboard
import RxSwift
RxKeyboard.instance.frame
.drive(onNext: { frame in
print("Keyboard frame: \(frame)")
})
.disposed(by: disposeBag)
- Adjusting view constraints based on keyboard visibility:
import RxKeyboard
import RxSwift
import RxCocoa
RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyboardVisibleHeight in
self?.view.layoutIfNeeded()
self?.bottomConstraint.constant = keyboardVisibleHeight
UIView.animate(withDuration: 0.3) {
self?.view.layoutIfNeeded()
}
})
.disposed(by: disposeBag)
- Dismissing keyboard on tap gesture:
import RxKeyboard
import RxSwift
import RxCocoa
import UIKit
let tapGesture = UITapGestureRecognizer()
view.addGestureRecognizer(tapGesture)
tapGesture.rx.event
.subscribe(onNext: { _ in
self.view.endEditing(true)
})
.disposed(by: disposeBag)
Getting Started
- Install RxKeyboard using CocoaPods by adding the following to your Podfile:
pod 'RxKeyboard'
- Import RxKeyboard in your Swift file:
import RxKeyboard
- Start observing keyboard events:
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyboardVisibleHeight in
// Handle keyboard height changes
})
.disposed(by: disposeBag)
}
}
Competitor Comparisons
Reactive Programming in Swift
Pros of RxSwift
- Comprehensive reactive programming framework for Swift
- Large community and extensive documentation
- Supports a wide range of reactive programming patterns and operators
Cons of RxSwift
- Steeper learning curve for developers new to reactive programming
- Can lead to complex code if not used carefully
- Larger library size compared to more focused solutions
Code Comparison
RxSwift (general reactive programming):
Observable.from([1, 2, 3, 4, 5])
.filter { $0 % 2 == 0 }
.map { $0 * 2 }
.subscribe(onNext: { print($0) })
RxKeyboard (keyboard-specific reactive programming):
RxKeyboard.instance.visibleHeight
.drive(onNext: { height in
print("Keyboard height: \(height)")
})
.disposed(by: disposeBag)
Summary
RxSwift is a comprehensive reactive programming framework for Swift, offering a wide range of features and patterns. It has a large community and extensive documentation but comes with a steeper learning curve and potential for complex code. RxKeyboard, on the other hand, is a focused library specifically for handling keyboard events reactively. It builds on top of RxSwift, providing a simpler API for keyboard-related tasks. While RxSwift is more versatile, RxKeyboard offers a streamlined solution for keyboard management in iOS applications.
Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.
Pros of ReactiveCocoa
- More comprehensive framework for reactive programming in Swift and Objective-C
- Supports a wider range of reactive patterns and operators
- Larger community and ecosystem with more resources and extensions
Cons of ReactiveCocoa
- Steeper learning curve due to its broader scope
- Potentially more complex setup and integration for simple use cases
- Heavier framework with more overhead compared to RxKeyboard
Code Comparison
ReactiveCocoa:
let (signal, observer) = Signal<String, Never>.pipe()
signal.observeValues { value in
print("Received value: \(value)")
}
observer.send(value: "Hello, ReactiveCocoa!")
RxKeyboard:
RxKeyboard.instance.frame
.drive(onNext: { frame in
print("Keyboard frame: \(frame)")
})
.disposed(by: disposeBag)
ReactiveCocoa provides a more general-purpose reactive programming framework, while RxKeyboard focuses specifically on handling keyboard events in iOS applications. ReactiveCocoa offers greater flexibility and a wider range of reactive programming capabilities, but it may be overkill for projects that only need keyboard handling. RxKeyboard, on the other hand, provides a simpler and more targeted solution for keyboard-related reactive programming, making it easier to integrate for specific use cases.
A Swift binding framework
Pros of Bond
- More comprehensive reactive programming framework, offering a wider range of features beyond keyboard handling
- Supports data binding and UI synchronization, making it suitable for larger, more complex applications
- Provides a declarative approach to UI development, potentially simplifying code structure
Cons of Bond
- Steeper learning curve due to its broader scope and more extensive API
- May introduce unnecessary complexity for projects that only require keyboard handling
- Larger library size, which could impact app size and compilation time
Code Comparison
RxKeyboard:
RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyboardVisibleHeight in
self?.tableViewBottomConstraint.constant = keyboardVisibleHeight
})
.disposed(by: disposeBag)
Bond:
let keyboardHeight = Observable<CGFloat>()
keyboardHeight
.bind(to: tableViewBottomConstraint.constant)
.dispose(in: bag)
While both libraries use reactive programming concepts, Bond's approach is more generalized and can be applied to various UI elements beyond just keyboard handling. RxKeyboard provides a more specialized solution focused specifically on keyboard interactions.
Network abstraction layer written in Swift.
Pros of Moya
- More comprehensive networking abstraction layer
- Supports multiple request types and response handling
- Extensive documentation and community support
Cons of Moya
- Steeper learning curve due to its broader scope
- May be overkill for simple API interactions
- Requires more setup and configuration
Code Comparison
RxKeyboard:
RxKeyboard.instance.frame
.drive(onNext: { frame in
// Handle keyboard frame changes
})
.disposed(by: disposeBag)
Moya:
provider = MoyaProvider<MyAPI>()
provider.rx.request(.userProfile)
.map(User.self)
.subscribe(onSuccess: { user in
// Handle user data
})
.disposed(by: disposeBag)
Summary
While RxKeyboard focuses specifically on keyboard management in iOS applications, Moya is a more comprehensive networking library. RxKeyboard provides a simpler, more targeted solution for keyboard-related tasks, while Moya offers a robust framework for handling various API interactions. The choice between the two depends on the specific needs of your project. If you only need keyboard management, RxKeyboard might be more suitable. However, if you're looking for a full-featured networking solution, Moya would be the better choice despite its steeper learning curve.
A library for reactive and unidirectional Swift applications
Pros of ReactorKit
- Provides a comprehensive architecture for building reactive apps
- Offers a clear separation of concerns with its unidirectional data flow
- Supports easy testing with a view-independent business logic layer
Cons of ReactorKit
- Steeper learning curve due to its more complex architecture
- May be overkill for simpler applications
- Requires more boilerplate code compared to RxKeyboard
Code Comparison
ReactorKit:
struct Reactor: ReactorKit.Reactor {
enum Action { case increment, decrement }
enum Mutation { case increaseValue, decreaseValue }
struct State { var value: Int = 0 }
func mutate(action: Action) -> Observable<Mutation>
func reduce(state: State, mutation: Mutation) -> State
}
RxKeyboard:
RxKeyboard.instance.visibleHeight
.drive(onNext: { keyboardVisibleHeight in
// Handle keyboard height changes
})
.disposed(by: disposeBag)
ReactorKit is a full-fledged architecture for building reactive applications, while RxKeyboard focuses specifically on handling keyboard events in a reactive manner. ReactorKit offers more structure and scalability for complex apps, but comes with a steeper learning curve. RxKeyboard provides a simpler, more focused solution for keyboard management in RxSwift projects.
UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...)
Pros of RxDataSources
- More versatile, handling complex data structures for UITableView and UICollectionView
- Provides automatic diffing and animating of data changes
- Offers a more declarative approach to managing data sources
Cons of RxDataSources
- Steeper learning curve due to its more complex API
- May be overkill for simple table or collection views
- Requires more setup code compared to RxKeyboard's straightforward implementation
Code Comparison
RxDataSources:
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>(
configureCell: { (_, tv, indexPath, element) in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(element)"
return cell
}
)
RxKeyboard:
RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyboardVisibleHeight in
self?.view.frame.origin.y = -keyboardVisibleHeight
})
.disposed(by: disposeBag)
RxDataSources focuses on managing complex data structures for table and collection views, while RxKeyboard specifically handles keyboard-related events and animations. RxDataSources is more powerful but complex, whereas RxKeyboard is simpler and more focused on its specific use case.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
RxKeyboard
RxKeyboard provides a reactive way of observing keyboard frame changes. Forget about keyboard notifications. It also perfectly works with UIScrollViewKeyboardDismissMode.interactive
.
Getting Started
RxKeyboard provides two Driver
s.
/// An observable keyboard frame.
let frame: Driver<CGRect>
/// An observable visible height of keyboard. Emits keyboard height if the keyboard is visible
/// or `0` if the keyboard is not visible.
let visibleHeight: Driver<CGFloat>
/// Same with `visibleHeight` but only emits values when keyboard is about to show. This is
/// useful when adjusting scroll view content offset.
let willShowVisibleHeight: Driver<CGFloat>
Use RxKeyboard.instance
to get singleton instance.
RxKeyboard.instance
Subscribe RxKeyboard.instance.frame
to observe keyboard frame changes.
RxKeyboard.instance.frame
.drive(onNext: { frame in
print(frame)
})
.disposed(by: disposeBag)
Tips and Tricks
-
ð I want to adjust
UIScrollView
'scontentInset
to fit keyboard height.RxKeyboard.instance.visibleHeight .drive(onNext: { [scrollView] keyboardVisibleHeight in scrollView.contentInset.bottom = keyboardVisibleHeight }) .disposed(by: disposeBag)
-
ð I want to adjust
UIScrollView
'scontentOffset
to fit keyboard height.RxKeyboard.instance.willShowVisibleHeight .drive(onNext: { [scrollView] keyboardVisibleHeight in scrollView.contentOffset.y += keyboardVisibleHeight }) .disposed(by: disposeBag)
-
ð I want to make
UIToolbar
move along with the keyboard in an interactive dismiss mode. (Just like the wonderful GIF above!)If you're not using Auto Layout:
RxKeyboard.instance.visibleHeight .drive(onNext: { [toolbar, view] keyboardVisibleHeight in toolbar.frame.origin.y = view.frame.height - toolbar.frame.height - keyboardVisibleHeight }) .disposed(by: disposeBag)
If you're using Auto Layout, you have to capture the toolbar's bottom constraint and set
constant
to keyboard visible height.RxKeyboard.instance.visibleHeight .drive(onNext: { [toolbarBottomConstraint] keyboardVisibleHeight in toolbarBottomConstraint.constant = -1 * keyboardVisibleHeight }) .disposed(by: disposeBag)
Note: In real world, you should use
setNeedsLayout()
andlayoutIfNeeded()
with animation block. See the example project for example. -
Anything else? Please open an issue or make a Pull Request.
Dependencies
Requirements
- Swift 5.1
- iOS 9+
Contributing
In development, RxKeyboard manages dependencies with Swift Package Manager. Use the command below in order to generate a Xcode project file. Note that .xcodeproj
file changes are not tracked via git.
$ swift package generate-xcodeproj
Installation
-
Using CocoaPods:
pod 'RxKeyboard'
-
Using Carthage:
binary "https://raw.githubusercontent.com/RxSwiftCommunity/RxKeyboard/master/RxKeyboard.json"
â ï¸ With Carthage, RxKeyboard only supports binary installation:
- 0.9.2
- Xcode 10.1 (10B61)
- Swift 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
- 0.9.0
- Xcode 10 (10A255)
- Swift 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
- 0.8.2
- Xcode 9.3 (9E145)
- Swift 4.1.0 (swiftlang-902.0.48 clang-902.0.37.1)
- 0.7.1
- Xcode 9.1 (9B55)
- Swift 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38)
- 0.7.0
- 9.0.1 (9A1004)
- Swift 4.0 (swiftlang-900.0.65.2 clang-900.0.37)
- 0.9.2
License
RxKeyboard is under MIT license.
Top Related Projects
Reactive Programming in Swift
Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.
A Swift binding framework
Network abstraction layer written in Swift.
A library for reactive and unidirectional Swift applications
UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...)
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot