[英]How to add a statefull widget or view in another screen at the bottom
I have created an animated radio circular button as shown in the below image:我创建了一个动画单选圆形按钮,如下图所示:
and this is the below code:这是下面的代码:
import 'package:flutter/material.dart';
import 'package:catest/utils/animated_radio_btn.dart';
class RadioBtnSim extends StatefulWidget {
RadioBtnSim({Key key, this.title}) : super(key: key);
final String title;
String radioValue = 'First';
// final bool showFavs;
// PropertiesGrid(this.showFavs);
@override
_RadioBtnSimState createState() => _RadioBtnSimState();
}
class _RadioBtnSimState extends State<RadioBtnSim> with SingleTickerProviderStateMixin {
_RadioBtnSimState() {
customBuilder = (BuildContext context, List<dynamic> animValues, Function updateState, String value) {
return GestureDetector(
onTap: () {
setState(() {
widget.radioValue = value;
});
},
child: Container(
width: double.infinity,
height: animValues[0] * 40 + 60,
color: animValues[1],
child: Center(
child: Text(
value
)
),
),
);
};
simpleBuilder = (BuildContext context, List<double> animValues, Function updateState, String value) {
final alpha = (animValues[0] * 255).toInt();
return GestureDetector(
onTap: () {
setState(() {
widget.radioValue = value;
});
},
child: Container(
padding: EdgeInsets.all(32.0),
margin: EdgeInsets.symmetric(horizontal: 2.0, vertical: 12.0),
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).primaryColor.withAlpha(alpha),
border: Border.all(
color: Theme.of(context).primaryColor.withAlpha(255 - alpha),
width: 4.0,
)
),
child: Text(
value,
style: Theme.of(context).textTheme.body1.copyWith(fontSize: 20.0),
)
)
);
};
dynamicBuilder = (BuildContext context, List<dynamic> animValues, Function updateState, String value) {
return GestureDetector(
onTap: () {
setState(() {
widget.radioValue = value;
});
},
child: Container(
alignment: Alignment.center,
margin: EdgeInsets.symmetric(horizontal: 4.0, vertical: 12.0),
padding: EdgeInsets.all(32.0 + animValues[0] * 12.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: animValues[1],
border: Border.all(
color: animValues[2],
width: 2.0
)
),
child: Text(
value,
style: Theme.of(context).textTheme.body1.copyWith(
fontSize: 20.0,
color: animValues[2]
),
)
)
);
};
}
RadioBuilder<String, dynamic> customBuilder;
RadioBuilder<String, double> simpleBuilder;
RadioBuilder<String, dynamic> dynamicBuilder;
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
var animationController = AnimationController(
duration: Duration(milliseconds: 100),
vsync: this
);
_controller = animationController;
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.ease
);
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CustomRadio<String, dynamic>(
value: 'Sim 1',
groupValue: widget.radioValue,
animsBuilder: (AnimationController controller) => [
CurvedAnimation(
parent: controller,
curve: Curves.easeInOut
),
ColorTween(
begin: Colors.white,
end: Colors.deepPurple
).animate(controller),
ColorTween(
begin: Colors.deepPurple,
end: Colors.white
).animate(controller),
],
builder: dynamicBuilder,
),
CustomRadio<String, dynamic>(
value: 'Sim 2',
groupValue: widget.radioValue,
animsBuilder: (AnimationController controller) => [
CurvedAnimation(
parent: controller,
curve: Curves.easeInOut
),
ColorTween(
begin: Colors.white,
end: Colors.deepPurple
).animate(controller),
ColorTween(
begin: Colors.deepPurple,
end: Colors.white
).animate(controller),
],
builder: dynamicBuilder,
),
]
),
],
);
}
}
and now I have another screen as the below:现在我有另一个屏幕如下:
and this is the below related code:这是以下相关代码:
import 'package:flutter/material.dart';
import 'package:catest/config/app_theme.dart';
import '../widgets/radio_btn_sim.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
top: 100,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Sim information',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Sim operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Image.asset(
'assets/images/sim_ic.png',
width: 30,
height: 30,
),
Text('ICCID'),
],
)),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('IMEI')),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('SIM IMSI')),
DataCell(Text('123456789')),
]),
],
),
),
],
),
),
//Network provider
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Network Provider',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone NL'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('MCC'),
],
)),
DataCell(Text('204')),
]),
DataRow(cells: [
DataCell(Text('MNC')),
DataCell(Text('04')),
]),
],
),
),
],
),
),
//Serving Cell
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Serving Cell',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Data Net')),
DataColumn(
label: Row(
children: <Widget>[
Text('LTE'),
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('Data type'),
],
)),
DataCell(Text('LTE')),
]),
DataRow(cells: [
DataCell(Text('TAC')),
DataCell(Text('62603')),
]),
DataRow(cells: [
DataCell(Text('PCI')),
DataCell(Text('118')),
]),
DataRow(cells: [
DataCell(Text('ECI')),
DataCell(Text('12315644(5465-567)')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('FREQ')),
DataCell(Text('1815/1720')),
]),
DataRow(cells: [
DataCell(Text('BAND')),
DataCell(Text('3 FDD')),
]),
],
),
),
],
),
),
],
),
);
}
}
So now I want to put the radio button I created at the bottom of the HomeScreen
to be like the below image:所以,现在我想把在底部创建的单选按钮我
HomeScreen
是像下面的图片:
and this is the utils
or animation part
:这是
utils
或animation part
:
library custom_radio;
import 'package:flutter/material.dart';
typedef AnimationsBuilder<T> = List<Animation<T>> Function(AnimationController);
typedef RadioBuilder<T, U> = Widget Function(BuildContext context, List<U> animValues, Function updateState, T value);
class CustomRadio<T, U> extends StatefulWidget {
final RadioBuilder<T, U> builder;
/// The duration of the animation controller
final Duration duration;
/// Returns the list of child animations whose values will be passed to the builder.
/// Called on initState.
final AnimationsBuilder<U> animsBuilder;
final T value;
final T groupValue;
bool get checked => value == groupValue;
CustomRadio({
Key key,
this.animsBuilder,
this.duration = const Duration(milliseconds: 600),
@required this.builder,
@required this.value,
@required this.groupValue,
}) : assert(duration != null),
super(key: key);
@override
State<CustomRadio> createState() => _CustomRadioState<T, U>();
}
class _CustomRadioState<T, U> extends State<CustomRadio<T, U>>
with SingleTickerProviderStateMixin {
AnimationController _controller;
List<Animation> _animations;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: widget.duration, vsync: this);
_animations = widget.animsBuilder(_controller);
_animations.forEach((anim) => anim.addListener(() => setState(() {})));
if (widget.checked)
_controller.value = 1.0;
else
_controller.value = 0.0;
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
void _updateState() {
setState(() {
if (widget.checked && _controller.status != AnimationStatus.completed) {
_controller.forward();
} else {
_controller.reverse();
}
});
}
@override
Widget build(BuildContext context) {
if ((widget.checked &&
(_controller.status == AnimationStatus.dismissed ||
_controller.status == AnimationStatus.reverse)) ||
(!widget.checked &&
(_controller.status == AnimationStatus.completed ||
_controller.status == AnimationStatus.forward))) {
_updateState();
}
final anims = _animations.map<U>((anim) => anim.value).toList();
return widget.builder(
context,
anims.length > 0 ? anims : [widget.checked].cast<dynamic>(),
_updateState,
widget.value,
);
}
}
I hope this would be clear enough, and sorry if there's any missing information :)..我希望这足够清楚,如果有任何遗漏的信息,我很抱歉:)。
you can use a Stack
widget as parent widget and add the two screens on it.您可以使用
Stack
小部件作为父小部件并在其上添加两个屏幕。 Then wrap the RadioBtnSim
widget with a Positioned
widget with bottom=0.0
property.然后使用具有
bottom=0.0
属性的Positioned
小部件包装RadioBtnSim
小部件。
You can use Stack
and Positioned
to position the sim card buttons on top of the table:您可以使用
Stack
和Positioned
将 SIM 卡按钮定位在表格顶部:
Stack(
children: <Widget>[
SingleChildScrollView( // this is the SingleChildScrollView that is placed inside homepage
child: Column(
children: [
...
]
),
),
Positioned(
bottom: 10,
child: Container(
width: MediaQuery.of(context).size.width,
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CustomRadio<String, dynamic>(
...
),
CustomRadio<String, dynamic>(
...
),
],
),
),
),
)
],
)
Use a Stack
and Positioned
widget in your Home screen:在主屏幕中使用
Stack
and Positioned
小部件:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
top: 100,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Sim information',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Sim operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Image.asset(
'assets/images/sim_ic.png',
width: 30,
height: 30,
),
Text('ICCID'),
],
)),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('IMEI')),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('SIM IMSI')),
DataCell(Text('123456789')),
]),
],
),
),
],
),
),
//Network provider
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Network Provider',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone NL'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('MCC'),
],
)),
DataCell(Text('204')),
]),
DataRow(cells: [
DataCell(Text('MNC')),
DataCell(Text('04')),
]),
],
),
),
],
),
),
//Serving Cell
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Serving Cell',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Data Net')),
DataColumn(
label: Row(
children: <Widget>[
Text('LTE'),
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('Data type'),
],
)),
DataCell(Text('LTE')),
]),
DataRow(cells: [
DataCell(Text('TAC')),
DataCell(Text('62603')),
]),
DataRow(cells: [
DataCell(Text('PCI')),
DataCell(Text('118')),
]),
DataRow(cells: [
DataCell(Text('ECI')),
DataCell(Text('12315644(5465-567)')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('FREQ')),
DataCell(Text('1815/1720')),
]),
DataRow(cells: [
DataCell(Text('BAND')),
DataCell(Text('3 FDD')),
]),
],
),
),
],
),
),
],
),
),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: RadioBtnSim(
),
),
),
],
),
);
}
}
Remove the Scaffold
present in the RadioBtnSim
.拆下
Scaffold
存在于RadioBtnSim
。
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CustomRadio<String, dynamic>(
value: 'Sim 1',
groupValue: widget.radioValue,
animsBuilder: (AnimationController controller) => [
CurvedAnimation(parent: controller, curve: Curves.easeInOut),
ColorTween(begin: Colors.white, end: Colors.deepPurple)
.animate(controller),
ColorTween(begin: Colors.deepPurple, end: Colors.white)
.animate(controller),
],
builder: dynamicBuilder,
),
CustomRadio<String, dynamic>(
value: 'Sim 2',
groupValue: widget.radioValue,
animsBuilder: (AnimationController controller) => [
CurvedAnimation(parent: controller, curve: Curves.easeInOut),
ColorTween(begin: Colors.white, end: Colors.deepPurple)
.animate(controller),
ColorTween(begin: Colors.deepPurple, end: Colors.white)
.animate(controller),
],
builder: dynamicBuilder,
),
],
);
OUTPUT:输出:
import 'package:flutter/material.dart';
import 'package:catest/config/app_theme.dart';
import '../widgets/radio_btn_sim.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Stack(
children: <Widget>[
_buildScreen(),
Positioned(
bottom: 10.0,
child: RadioBtnSim(),
),
];
);
);
}
Widget _buildScreen() {
return
```Column(
children: [
Padding(
padding: const EdgeInsets.only(
top: 100,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Sim information',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Sim operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Image.asset(
'assets/images/sim_ic.png',
width: 30,
height: 30,
),
Text('ICCID'),
],
)),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('IMEI')),
DataCell(Text('123456789')),
]),
DataRow(cells: [
DataCell(Text('SIM IMSI')),
DataCell(Text('123456789')),
]),
],
),
),
],
),
),
//Network provider
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Network Provider',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Operator')),
DataColumn(
label: Row(
children: <Widget>[
Text('Vodafone NL'),
Image.asset(
'assets/images/vodic.png',
width: 30,
height: 30,
)
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('MCC'),
],
)),
DataCell(Text('204')),
]),
DataRow(cells: [
DataCell(Text('MNC')),
DataCell(Text('04')),
]),
],
),
),
],
),
),
//Serving Cell
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Serving Cell',
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(
left: 30,
),
child: DataTable(
columns: [
DataColumn(label: Text('Data Net')),
DataColumn(
label: Row(
children: <Widget>[
Text('LTE'),
],
)),
],
rows: [
DataRow(cells: [
DataCell(Row(
children: <Widget>[
Text('Data type'),
],
)),
DataCell(Text('LTE')),
]),
DataRow(cells: [
DataCell(Text('TAC')),
DataCell(Text('62603')),
]),
DataRow(cells: [
DataCell(Text('PCI')),
DataCell(Text('118')),
]),
DataRow(cells: [
DataCell(Text('ECI')),
DataCell(Text('12315644(5465-567)')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('EARFCN')),
DataCell(Text('1300/19300')),
]),
DataRow(cells: [
DataCell(Text('FREQ')),
DataCell(Text('1815/1720')),
]),
DataRow(cells: [
DataCell(Text('BAND')),
DataCell(Text('3 FDD')),
]),
],
),
),
],
),
),
],
);
}
}
also you need a callback from RadioBtnSim into HomeScreen to have the selected value您还需要从 RadioBtnSim 回调到 HomeScreen 以获得所选值
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.