gpt4 book ai didi

具有固定底部和可滚动上部的 Flutter 布局

转载 作者:IT王子 更新时间:2023-10-29 07:13:08 25 4
gpt4 key购买 nike

我目前正在为类似信息亭的设备编写 Flutter 应用程序。该设备将以横向模式安装,并在底部集成条形码扫描器。

设备将几乎所有时间都花在一个布局上:

Standard Layout w/o Keyboard

目前整个body在一个SingleChildScrollView中。这允许 View 在用户点击文本输入框时“向上滑动”。然后当键盘关闭时, View 会“滑”回。

With Keyboard Active

我想做的是将底部的“下方扫描票证”行固定到 View 底部,至少在可见时(当键盘未覆盖它时)。截至目前,它是一个弹性布局,并没有完全到达底部。

查看带有调试油漆的图像:粉色框应该在底部,它上面的所有内容都应该在可 ScrollView 中。 View with Debug Box Paint

我开始摆弄多种选择。我不想要固定位置,因为我们最终也会在具有各种屏幕尺寸的 iDevices 上提供解决方案。

这是我目前的脚手架体:

Container(
constraints: BoxConstraints.expand(),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 50.0, bottom: 20.0),
child: Text(_message ?? "Welcome!",
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 45.0, color: Colors.black)),
),
Padding(
padding: EdgeInsets.all(20.0),
child: Text("Scan ticket below or Search for your Transaction",
style:
TextStyle(fontSize: 25.0, color: Colors.black)),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
flex: 4,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 50.0, vertical: 25.0),
color: skidataThemeData.primaryColor,
padding: const EdgeInsets.symmetric(
horizontal: 25.0, vertical: 25.0),
child: Center(
child: new TextFormField(
//This autofocus works, but during transition from successful plate val to
//this page, the keyoard is activated during transition causing an overflow on the
//applyValidationScreen.
//autofocus: true,
style: new TextStyle(
decorationColor:
skidataThemeData.accentColor,
fontSize: 90.0,
color: skidataThemeData.accentColor),
textAlign: TextAlign.center,
onSaved: (String value) {
this._data.plateNumber = value;
},
decoration: new InputDecoration(
hintText: "Enter Data",
hintStyle: new TextStyle(
color: Colors.white),
fillColor:
skidataThemeData.accentColor,
contentPadding: EdgeInsets.all(1.0),
border: InputBorder.none),
validator: (value) {
if (value.isEmpty) {
return 'Field cannot be blank.';
}
},
autocorrect: false,
),
))),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(25.0),
child: RaisedButton(
padding: EdgeInsets.all(15.0),
color: skidataThemeData.accentColor,
onPressed: () async {
FocusScope.of(context)
.requestFocus(new FocusNode());
setState(() {
_message = '';
});

if (_formKey.currentState.validate()) {
// If the form is valid, we want to show a Snackbar
Scaffold.of(context).showSnackBar(
new SnackBar(
content: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
new CircularProgressIndicator(
valueColor:
new AlwaysStoppedAnimation<
Color>(
skidataThemeData
.primaryColor),
),
Text(
'Search for matching record..',
style: new TextStyle(
color: skidataThemeData
.primaryColor))
],
),
backgroundColor:
skidataThemeData.accentColor,
duration: Duration(seconds: 10)),
);
await new Future.delayed(
const Duration(milliseconds: 1000));

Scaffold.of(context)
.hideCurrentSnackBar();

Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
new SvalKioskApp()),
);
} else {
setState(() {
_message = "";
});
}
},
child: new Text('Search for Record',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0, color: Colors.black)),
),
))
]),
Container(
color: Colors.pink,
child: Padding(
padding: const EdgeInsets.only(top:40.0),
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 5.0),
child: Image.asset(
'images/downarrow.png',
fit: BoxFit.contain,
),
)),
Expanded(
flex: 5,
child: Center(
child: Text("Scan Physical Ticket Below!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 45.0)))),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 5.0),
child: Image.asset(
'images/downarrow.png',
fit: BoxFit.contain,
),
)),
]),
),
)
]),
),
)

最佳答案

今天早上我在洗澡的时候想到了这个解决方案:

从一列开始,您将其分成两个展开的小部件以获得所需的顶部/底部部分比例。

然后在每个 Expanded 中,使一个子容器展开以填充空间。在顶部容器中,将对齐设置为 topCenter,并将底部容器对齐设置为 bottomCenter

在顶部容器中,添加一个 SingleChildScrollView 子项。现在上部是可滚动的,底部是固定的。

  Widget getInputView() {
return Builder(
builder: (context) => Container(
constraints: BoxConstraints.expand(),
child: Column(
children: <Widget>[
Expanded(
flex: 4,
child: Container(
alignment: Alignment.topCenter,
constraints: BoxConstraints.expand(),
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Text("${_kiosk.kioskName}",
textAlign: TextAlign.end)
]),
),
Padding(
padding: EdgeInsets.symmetric(vertical:30.0),
child: Text(
_kiosk.displayMessage ?? "Welcome!",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 45.0,
color: Colors.black)),
),
Padding(
padding: EdgeInsets.all(20.0),
child: Text(
"Scan barcode below or enter search data in box.",
style: TextStyle(
fontSize: 25.0,
color: Colors.black)),
),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
flex: 4,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 50.0,
vertical: 25.0),
color: themeData
.primaryColor,
padding: const EdgeInsets
.symmetric(
horizontal: 25.0,
vertical: 25.0),
child: Center(
child: new TextFormField(
//This autofocus works, but during transition from successful plate val to
//this page, the keyoard is activated during transition causing an overflow on the
//applyValidationScreen.
//autofocus: true,
style: new TextStyle(
decorationColor:
themeData
.accentColor,
fontSize: 90.0,
color:
themeData
.accentColor),
textAlign:
TextAlign.center,
onSaved: (String value) {
this._data.plateNumber =
value;
},
decoration: new InputDecoration(
hintText:
"Enter Data",
hintStyle:
new TextStyle(
color: Colors
.white),
fillColor:
themeData
.accentColor,
contentPadding:
EdgeInsets.all(
1.0),
border:
InputBorder.none),
validator: (value) {
if (value.isEmpty) {
return 'Field cannot be blank.';
}
},
autocorrect: false,
),
))),
Expanded(
flex: 1,
child: Padding(
padding:
const EdgeInsets.all(25.0),
child: RaisedButton(
padding: EdgeInsets.all(15.0),
color: themeData
.accentColor,
onPressed: () async {
FocusScope.of(context)
.requestFocus(
new FocusNode());

if (_formKey.currentState
.validate()) {
// If the form is valid, we want to show a Snackbar
Scaffold.of(context)
.showSnackBar(
new SnackBar(
content: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
new CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<
Color>(
themeData
.primaryColor),
),
Text(
'Search for matching ticket..',
style: new TextStyle(
color: themeData
.primaryColor))
],
),
backgroundColor:
themeData
.accentColor,
duration: Duration(
seconds: 10)),
);
await new Future.delayed(
const Duration(
milliseconds:
1000));
PlateMatchResponse resp =
await this.submit();

Scaffold.of(context)
.hideCurrentSnackBar();

Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
new SvalKioskApp()),
);
}
},
child: new Text(
'Search for Data Match',
textAlign:
TextAlign.center,
style: TextStyle(
fontSize: 25.0,
color: Colors.black)),
),
))
]),
]),
),
))),
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(25.0),
alignment: Alignment.bottomCenter,
constraints: BoxConstraints.expand(),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 5.0),
child: Image.asset(
'images/downarrow.png',
fit: BoxFit.contain,
),
)),
Expanded(
flex: 5,
child: Center(
child: Text(
"Scan Physical Ticket Below",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 45.0)))),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 5.0),
child: Image.asset(
'images/downarrow.png',
fit: BoxFit.contain,
),
)),
])))
],
),
));

关于具有固定底部和可滚动上部的 Flutter 布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53329366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com