Repository navigation
[IOS] SafeArea maintainBottomViewPadding is not respected when keyboard viewInsets are animated #97609
Description
This issue has been introduced as a result of the changes to the flutter engine (iOS) made in PR 29281 (flutter-team-archive/engine#29281). Those changes are in use on the current master and dev branch of this project.
It is now possible for MediaqQuery viewInsets.bottom to be >0 AND for padding.bottom >0 during the keyboard transition. This results in the maintainBottomViewPadding property being ignored within SafeArea build() at various times during the animation.
Steps to Reproduce
- Execute
flutter runon the code sample - Tap on the TextField to reveal the software keyboard
- Tap 'done' to remove the software keyboard
Expected results:
The keyboard should overlay the app and not affect the layout of any widgets. In particular, the SafeArea padding at the bottom of the orange widget should remain unchanged regardless of the viewInsets.bottom value created by the keyboard since maintainBottomViewPadding is set to true.
Actual results:
During animation, the orange widget 'jumps' downward. It is laid out differently during the animation indicating that the bottom viewPadding is not always respected, despite maintainBottomViewPadding being set to true.
Code sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: const Text('SafeArea Demo'),
),
body: Center(
child: Column(
children: <Widget>[
const Expanded(
child: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Text("This scaffold has resizeToAvoidBottomInset=false"),
)),
SafeArea(
maintainBottomViewPadding: true,
child: Container(
color: const Color.fromARGB(255, 255, 72, 0),
height: 500,
child: Column(
children: const [
Text(
'This container is surrounded by a SafeArea \n with maintainBottomViewPadding=true',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(width: 200, child: TextField()),
],
),
),
),
],
),
),
);
}
}Logs
No relevant runtime logs
No issues found! (ran in 1.8s)
[✓] Flutter (Channel master, 2.10.0-1.0.pre.373, on macOS 12.1 21C52 darwin-x64, locale en-GB)
• Flutter version 2.10.0-1.0.pre.373 at /Users/joellurcook/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision a22cf5d6b9 (28 minutes ago), 2022-02-02 09:16:05 +0100
• Engine revision 0bd729b972
• Dart version 2.17.0 (build 2.17.0-74.0.dev)
• DevTools version 2.10.0
[!] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/joellurcook/Library/Android/sdk
✗ cmdline-tools component is missing
Run `path/to/sdkmanager --install "cmdline-tools;latest"`
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Android Studio 2.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
[✓] IntelliJ IDEA Community Edition (version 2021.1.3)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.63.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.34.0
[✓] Connected device (2 available)
• iPhone 13 (mobile) • 63C9A42F-6841-4F83-8922-DCAE0C900EBE • ios • com.apple.CoreSimulator.SimRuntime.iOS-15-2 (simulator)
• Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.99
[✓] HTTP Host Availability
• All required HTTP hosts are available
! Doctor found issues in 1 category.
Activity
joellurcook commentedon Feb 2, 2022
The offending line in SafeArea is:
I shall raise a PR with a more suitable condition
maheshj01 commentedon Feb 2, 2022
Hi @joellurcook, Thanks for filing the issue. I am able to reproduce the issue on
stable andthe master channel and works fine on stable, This seems to be a regression affecting IOS platforms and works fine on Android.Screen.Recording.2022-02-02.at.3.10.24.PM.mov
Screen.Recording.2022-02-02.at.3.00.26.PM.mov
Screen.Recording.2022-02-02.at.3.04.53.PM.mov
✅ : No Issue ❌: Issue reproduced
flutter doctor -v
[-]SafeArea maintainBottomViewPadding is not respected when keyboard viewInsets are animated[/-][+][IOS] SafeArea maintainBottomViewPadding is not respected when keyboard viewInsets are animated[/+]joellurcook commentedon Feb 2, 2022
Hi @maheshmnj
Thanks for confirming. I notice your Android video shows software back buttons. This would create a MediaQuery viewInsets.bottom, but not a viewPadding.bottom, which is required to see the problem. You would need an android device with a notch at the bottom and hardware buttons to replicate the issue. Unfortunately adding a notch to my AVD (and removing the software buttons) does not result in flutter reporting any bottom inset/padding - I'm not sure if this is another Flutter bug or an issue with emulated notches.
I suspect that the issue would occur on Android if you could find such a device. I believe viewInset animation for software keyboard has been available for Android for some time, so the bug may be quite an old one, just very hard to see before being introduced to iOS.
Simplify SafeArea test for maintainBottomViewPadding.
HansMuller commentedon Feb 2, 2022
CC @gaaclarke
jmagman commentedon Feb 2, 2022
@luckysmg
gaaclarke commentedon Feb 2, 2022
I've reviewed everything again.
The sample code makes sense. The desired behavior is that the app won't shrink when the keyboard is presented and that the widget is fixed to the bottom of the screen even when the keyboard is presented. In practice that would put you at the risk of having a Text widget that is obscured by the keyboard. But if the orientation is locked and the widget is high enough it could be a valid use case.
The engine PR is correct, meaning I don't think it's doing something incorrect that is causing the visual glitch. The engine PR is modifying the view inset but the reproduction code is explicitly saying it doesn't care about the view inset when laying out the widget. This validates the OP's suggestion that the fix may be in the framework. I'm not that familiar with that code. I'll read it over and the OPs suggestion to see if that makes sense to me.
Let me know if you think I'm missing something.
luckysmg commentedon Feb 3, 2022
I will take a look,both the engine code and framework code.
@gaaclarke @jmagman @joellurcook
luckysmg commentedon Feb 3, 2022
I wrote some debug code in sample code:
And When I tap the textField,the keyboard animation begin,and I get the log below:
Debug Logs
We can see from log that.
The
viewPaddingis always 34.0(which is the ios safeArea height).The
paddingis from 34 to 0And Here is the code in
SafeAreawidget'sbuild(context)methodWe can see the code here:
When animation is running,we can pick the first log data as example:
This data will make the condition:
data.padding.bottom == 0.0 && data.viewInsets.bottom != 0.0 && maintainBottomViewPaddingto false.So the
padding = padding.copyWith(bottom: data.viewPadding.bottom);will not execute....joellurcook commentedon Feb 3, 2022
To give an example use case... my app brings up popups from the bottom of the screen, of variable size, all of which have a SafeArea at the bottom. It also brings up the keyboard sometimes and disables the app UI when it does so. Because the UI is anyway disabled I want the keyboard to overlay - obscuring widgets is fine. Unles I specify
maintainBottomViewPadding, my popup SafeAreas will reduce to zero when the keyboard comes up, causing the popup to change height. This bug makes my popups behave just like the example app.joellurcook commentedon Feb 3, 2022
Hi @luckysmg
Yes, exactly that - see my PR with a suggested change to the condition you have mentioned.
luckysmg commentedon Feb 3, 2022
Oh I didn't see that. Yes,that 's it! 😀 @joellurcook
github-actions commentedon Mar 17, 2022
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.