Created
May 31, 2025 08:54
-
-
Save AndrewDongminYoo/9102d0725064c63c24a68dc04efc2356 to your computer and use it in GitHub Desktop.
A subscriber class for managing keyboard visibility events.
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 characters
| // 🎯 Dart imports: | |
| import 'dart:async'; | |
| // 🐦 Flutter imports: | |
| import 'package:flutter/services.dart'; | |
| /// A subscriber class for managing keyboard visibility events. | |
| /// | |
| /// This class allows registering callbacks for keyboard visibility changes, | |
| /// including when the keyboard is shown, hidden, or its visibility state changes. | |
| /// | |
| /// Provides methods to track and respond to keyboard visibility in a Flutter application. | |
| class KeyboardVisibilitySubscriber { | |
| KeyboardVisibilitySubscriber({ | |
| required this.onChange, | |
| this.onShow, | |
| this.onHide, | |
| }); | |
| /// A callback function that is triggered when the keyboard visibility changes. | |
| /// | |
| /// The [onChange] callback receives a boolean value indicating whether the keyboard is currently visible. | |
| final ValueChanged<bool> onChange; | |
| /// A callback function that is triggered when the keyboard is shown. | |
| /// | |
| /// This callback is invoked when the keyboard becomes visible on the screen. | |
| final VoidCallback? onShow; | |
| /// A callback function that is triggered when the keyboard is hidden. | |
| /// | |
| /// This callback is invoked when the keyboard becomes invisible on the screen. | |
| final VoidCallback? onHide; | |
| } | |
| /// Manages keyboard visibility events and provides a mechanism for subscribing to keyboard visibility changes. | |
| /// | |
| /// This class allows registering and tracking keyboard visibility listeners, | |
| /// handling events when the keyboard is shown, hidden, or its state changes. | |
| /// It provides a centralized way to monitor keyboard visibility across the application. | |
| class KeyboardVisibilityNotification { | |
| KeyboardVisibilityNotification() { | |
| _keyboardVisibilitySubscription ??= | |
| (_keyboardVisibilityStream.receiveBroadcastStream() as Stream<int>).listen(onKeyboardEvent); | |
| } | |
| /// A static [EventChannel] for receiving keyboard visibility events from the platform. | |
| /// | |
| /// This channel listens for keyboard visibility changes across the application, | |
| /// allowing tracking of when the keyboard is shown or hidden. | |
| static const _keyboardVisibilityStream = EventChannel('flutter_keyboard_visibility'); | |
| /// A static map to store keyboard visibility subscribers, keyed by their unique identifier. | |
| /// | |
| /// This map allows tracking and managing multiple keyboard visibility listeners | |
| /// within the [KeyboardVisibilityNotification] class, enabling efficient event | |
| /// distribution and listener management. | |
| static final Map<int, KeyboardVisibilitySubscriber> _list = <int, KeyboardVisibilitySubscriber>{}; | |
| /// A static [StreamSubscription] for managing the keyboard visibility event stream. | |
| /// | |
| /// This subscription allows listening to keyboard visibility changes and | |
| /// can be used to cancel the stream when no longer needed. | |
| static StreamSubscription<int>? _keyboardVisibilitySubscription; | |
| /// A static index used to generate unique identifiers for keyboard visibility subscribers. | |
| /// | |
| /// This variable ensures each subscriber receives a unique ID when registering | |
| /// with the [KeyboardVisibilityNotification] class, allowing for precise | |
| /// listener management and removal. | |
| static int _currentIndex = 0; | |
| /// Indicates whether the keyboard is currently visible on the screen. | |
| /// | |
| /// This boolean flag tracks the current visibility state of the keyboard, | |
| /// allowing components to respond to keyboard show/hide events. | |
| bool isKeyboardVisible = false; | |
| /// Handles keyboard visibility events by updating the keyboard visibility state | |
| /// and notifying all registered subscribers about the change. | |
| /// | |
| /// This method is called when a keyboard event is received from the platform. | |
| /// It updates the [isKeyboardVisible] flag and triggers corresponding callbacks | |
| /// for each registered subscriber, including the onChange, onShow, and onHide | |
| /// callbacks based on the current keyboard visibility state. | |
| /// | |
| /// @param arg An integer representing the keyboard visibility (1 for visible, 0 for hidden) | |
| void onKeyboardEvent(int arg) { | |
| isKeyboardVisible = arg == 1; | |
| _list.forEach((int index, KeyboardVisibilitySubscriber sub) { | |
| try { | |
| sub.onChange(isKeyboardVisible); | |
| if (isKeyboardVisible) { | |
| sub.onShow?.call(); | |
| } | |
| if (!isKeyboardVisible) { | |
| sub.onHide?.call(); | |
| } | |
| } catch (_) {} | |
| }); | |
| } | |
| /// Adds a new keyboard visibility listener with optional show and hide callbacks. | |
| /// | |
| /// Registers a new subscriber to track keyboard visibility changes. The method | |
| /// creates a [KeyboardVisibilitySubscriber] with the provided callbacks and | |
| /// assigns it a unique identifier. | |
| /// | |
| /// @param onChange A callback that is triggered with the current keyboard visibility state. | |
| /// @param onShow An optional callback triggered when the keyboard becomes visible. | |
| /// @param onHide An optional callback triggered when the keyboard becomes hidden. | |
| /// | |
| /// @return An integer representing the unique identifier for the registered listener. | |
| int addNewListener({ | |
| required ValueChanged<bool> onChange, | |
| VoidCallback? onShow, | |
| VoidCallback? onHide, | |
| }) { | |
| _list[_currentIndex] = KeyboardVisibilitySubscriber(onChange: onChange, onShow: onShow, onHide: onHide); | |
| return _currentIndex++; | |
| } | |
| /// Adds a new keyboard visibility subscriber to the list of listeners. | |
| /// | |
| /// Registers a [KeyboardVisibilitySubscriber] with a unique identifier and | |
| /// stores it in the internal listener collection. | |
| /// | |
| /// @param subscriber The keyboard visibility subscriber to be added. | |
| /// @return An integer representing the unique identifier for the registered subscriber. | |
| int addNewSubscriber(KeyboardVisibilitySubscriber subscriber) { | |
| _list[_currentIndex] = subscriber; | |
| return _currentIndex++; | |
| } | |
| /// Removes a keyboard visibility listener from the internal list of subscribers. | |
| /// | |
| /// Unregisters a previously added listener using its unique identifier. | |
| /// | |
| /// @param subscribingId The unique identifier of the listener to be removed. | |
| void removeListener(int subscribingId) { | |
| _list.remove(subscribingId); | |
| } | |
| /// Disposes of the keyboard visibility subscription if no listeners are active. | |
| /// | |
| /// Cancels the underlying keyboard visibility subscription and sets it to null | |
| /// when there are no more registered listeners. This helps clean up resources | |
| /// and prevent memory leaks when the keyboard visibility tracker is no longer needed. | |
| void dispose() { | |
| if (_list.isEmpty) { | |
| try { | |
| _keyboardVisibilitySubscription?.cancel().ignore(); | |
| } finally { | |
| _keyboardVisibilitySubscription = null; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment