keyboard: fix interactive dismiss race conditions, rewrite example

Fix several race conditions in the iOS interactive dismiss flow:
- Don't skip keyboard close notifications during pan tracking, which
  left Dart unaware the keyboard was dismissed
- Guard resignFirstResponder with generation check so reopened keyboards
  aren't killed by stale dismiss completions
- Block pan tracking from starting during an in-flight dismiss animation
- Always reset keyboard view bounds when the keyboard opens, not just
  when the dismiss animator is still running
- Handle duration=0 keyboard notifications by snapping immediately
- Gate adaptive learning debug output behind kDebugMode

Rewrite the example as a chat UI demonstrating ListenableBuilder,
scroll freeze during interactive dismiss, and proper bottom inset
handling with max(keyboardHeight, safeBottom).

Modernize example Android project from v1 to v2 embedding with
current AGP/Gradle versions.
This commit is contained in:
agra
2026-04-16 18:34:05 +03:00
parent 0be198e388
commit 8ac7b5a5d5
22 changed files with 591 additions and 327 deletions

View File

@@ -1,15 +1,24 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false
}
include ":app"