Flutter - 当键盘出现在android上时文本字段不显示
Posted
技术标签:
【中文标题】Flutter - 当键盘出现在android上时文本字段不显示【英文标题】:Flutter - Textfield not showing up when keyboard appears on android 【发布时间】:2020-12-11 12:06:39 【问题描述】:我的问题是,当我专注于文本字段时,键盘会出现,但布局不会调整大小以将其保留在视图中。这个问题只存在于 android 而不是 ios:这里是我的意思的截图:
在 android 上之前和之后:
iOS 之前和之后:
这是我的课:
class PlayerSelectionPage extends StatelessWidget
@override
Widget build(BuildContext context)
int itemCount = Provider.of<PlayerProvider>(context).getPlayerList.length;
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).translate('player_selection_page_title')),
),
floatingActionButton: FloatingActionButton(
onPressed: ()
HapticFeedback.mediumImpact();
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage(), settings: RouteSettings(name: 'Home page')));
,
child: Icon(
Icons.chevron_right,
size: 30,
color: Colors.white,
),
),
body: itemCount > 0 ? ListView.builder(
itemCount: itemCount,
itemBuilder: (context, index)
return Column(
children: [
PlayerDismissible(index),
Divider(
height: 0,
)
],
);
) : Container(
padding: EdgeInsets.all(20),
alignment: Alignment.topCenter,
child: Text(AppLocalizations.of(context).translate('player_selection_page_empty_text'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle2)
),
bottomSheet: BottomPlayerBar(),
);
这是我的 BottomPlayerBar() :
class BottomPlayerBar extends StatefulWidget
@override
_BottomPlayerBarState createState() => _BottomPlayerBarState();
class _BottomPlayerBarState extends State<BottomPlayerBar>
String playerName;
FocusNode myFocusNode;
@override
void initState()
super.initState();
myFocusNode = FocusNode();
SchedulerBinding.instance.addPostFrameCallback((_)
if (ModalRoute.of(context).isCurrent)
myFocusNode.requestFocus();
);
@override
Widget build(BuildContext context)
return Container(
height: 80, color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(top: 20, bottom: 25, left: 20, right: 70),
child: TextField(
focusNode: myFocusNode,
textCapitalization: TextCapitalization.words,
onChanged: (val) => playerName = val.trim(),
onSubmitted: (val)
if (playerName != null && playerName != '')
Provider.of<PlayerProvider>(context, listen: false).addPlayer(playerName);
HapticFeedback.lightImpact();
myFocusNode.requestFocus();
else
myFocusNode.unfocus();
,
maxLength: 19,
autocorrect: false,
decoration: new InputDecoration(
counterText: "",
border: new OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: const BorderRadius.all(
const Radius.circular(30.0),
),
),
filled: true,
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 20),
hintStyle: GoogleFonts.rubik(color: Colors.grey[500], fontWeight: FontWeight.bold),
hintText: AppLocalizations.of(context).translate('player_selection_page_hint'),
fillColor: Colors.white),
)
);
@override
void dispose()
super.dispose();
myFocusNode.dispose();
这是我的 android 清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="myApp">
<application
android:name="io.flutter.app.FlutterApplication"
android:label="myApp !"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.LaunchTheme"
android:resource="@style/LaunchTheme"
/>
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
【问题讨论】:
你能在android清单文件中发布设置吗 这里是,但我真的不知道它会有什么帮助。 因为你的 'android:windowSoftInputMode="adjustResize"'。它应该做你想做的事。 我应该删除这行吗? 没用... 【参考方案1】:android/app/src/main/res/values/styles.xml
对我来说,将下面的项目属性从 true 更改为 false
<item name="android:windowFullscreen">false</item>
我也有这个问题。由于使用了 flutter_native_splash 包而添加了这一行。
【讨论】:
非常感谢,这正是问题所在!【参考方案2】:在出现软键盘时调整页面大小是通过 AndroidManifest 中的android:windowSoftInputMode
活动参数处理的。见official documnetation
如果您的 AndroidManifest.xml 中有 android:windowSoftInputMode="adjustResize"
,则当软键盘出现时,文本字段将自动重新定位。 如果AndroidManifest.xml
中没有参数,则不会发生相同的行为
您能否通过修改您的 AndroidManifest.这也将解释为什么它不仅在 Android 中有效,而且在 iOS 中有效(因为 iOS 隐式处理)
P.S: 修改 AndoridManifest.xml 时,热重载可能不起作用。您将需要实际停止并开始运行应用程序。
【讨论】:
【参考方案3】:您可以使用 Transform Widget 包装您的 BottomPlayerBar 小部件,如下所示。
Transform.translate(
offset: Offset(0.0, -1 * MediaQuery.of(context).viewInsets.bottom),
child: BottomPlayerBar(),
);
【讨论】:
【参考方案4】:为您的 BottomPlayerBar 小部件使用边距:
margin: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
【讨论】:
【参考方案5】:您可以像这样使用stack
:
Widget build(BuildContext context)
return Scaffold(
body: Stack(
children: [
Column(
children: [
Flexible(
child: ListView.builder(itemBuilder: null),
),
Container(
width: double.infinity,
height: 100,
child: TextField(),
)
],
)
],
),
);
【讨论】:
【参考方案6】:一个简单的解决方案可能是为您的 BottomPlayerBar 使用底部填充,
而不是,
padding: EdgeInsets.only(top: 20, bottom: 25, left: 20, right: 70),
试试,
padding: EdgeInsets.only(top: 20, bottom: 25 + MediaQuery.of(context).padding.bottom, left: 20, right: 70),
这里我们只是添加添加到脚手架底部的任何填充
MediaQuery.of(context).padding.bottom
【讨论】:
【参考方案7】:这就是为什么我通常不尝试使用Scaffold
内置参数的原因。为了节省解决平台相关问题的时间,我会使用简单的Widgets
来实现您想要的结果。
Widget build(BuildContext context)
return Scaffold(
body: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// YOU BODY VIEW 85 HEIGHT %
ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height * 0.85,
),
child: MainWidget()
),
// YOUR BOTTOM VIEW 15 %
ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height * 0.15,
),
child: BottomPlayerBar()
),
],
),
),
);
对于你上面的例子PlayerSelectionPage
。
class PlayerSelectionPage extends StatelessWidget
@override
Widget build(BuildContext context)
int itemCount = Provider.of<PlayerProvider>(context).getPlayerList.length;
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).translate('player_selection_page_title')),
),
floatingActionButton: FloatingActionButton(
onPressed: ()
HapticFeedback.mediumImpact();
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage(), settings: RouteSettings(name: 'Home page')));
,
child: Icon(
Icons.chevron_right,
size: 30,
color: Colors.white,
),
),
body: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// NEW VIEW
ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height * 0.85,
),
child: itemCount > 0 ? ListView.builder(
itemCount: itemCount,
itemBuilder: (context, index)
return Column(
children: [
PlayerDismissible(index),
Divider(
height: 0,
)
],
);
) : Container(
padding: EdgeInsets.all(20),
alignment: Alignment.topCenter,
child: Text(AppLocalizations.of(context).translate('player_selection_page_empty_text'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle2)
),
),
// NEW VIEW
ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height * 0.15,
),
child: BottomPlayerBar()
),
],
),
),
body: itemCount > 0 ? ListView.builder(
itemCount: itemCount,
itemBuilder: (context, index)
return Column(
children: [
PlayerDismissible(index),
Divider(
height: 0,
)
],
);
) : Container(
padding: EdgeInsets.all(20),
alignment: Alignment.topCenter,
child: Text(AppLocalizations.of(context).translate('player_selection_page_empty_text'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle2)
),
);
【讨论】:
【参考方案8】:您可以将 isScrollControlled = true 添加到 showModalBottomSheet 中,它将允许底部工作表占据所需的全部高度,从而更加确保 TextField 不会被键盘覆盖。
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
backgroundColor: Colors.black,
context: context,
isScrollControlled: true,
builder: (context) => Padding(
padding: const EdgeInsets.symmetric(horizontal:18 ),
child: BottomPlayerBar(),
),
));
【讨论】:
以上是关于Flutter - 当键盘出现在android上时文本字段不显示的主要内容,如果未能解决你的问题,请参考以下文章