我创建了一个动画单选圆形按钮,如下图所示:
这是下面的代码:
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,
),
]
),
],
);
}
}
现在我有另一个屏幕如下:
这是下面的相关代码:
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')),
]),
],
),
),
],
),
),
],
),
);
}
}
因此,现在我想将我创建的单选按钮放在底部,HomeScreen
如下图所示:
这是utils
or 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,
);
}
}
我希望这会很清楚,如果有任何遗漏的信息,对不起:..
在主屏幕中使用Stack
和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(
),
),
),
],
),
);
}
}
删除中的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,
),
],
);
输出:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句