Я пытаюсь создать свой собственный сегмент в флаттере. Этот сегмент имеет две кнопки, одну для учителей и другую для студентов. То, что я пытаюсь сделать, это инкапсулировать кнопки в одном Stateful Widget для обработки setState обеих кнопок, потому что я хочу, чтобы кнопки были AnimatedContainer, и если я перестраиваю дочерние элементы (кнопки) из родительского элемента, переход не работает.
Обратите внимание, что кнопки расположены в стеке, и я переупорядочиваю содержимое, чтобы переместить нажатую кнопку поверх другой (это будет действовать, когда я установлю большую ширину в нажатой кнопке, теперь она еще не создана) ,
Вот мой код:
import 'package:flutter/cupertino.dart';
import '../../app_localizations.dart';
import '../../styles.dart';
GlobalKey<_ButtonState> teachersButtonKey = GlobalKey();
GlobalKey<_ButtonState> studentsButtonKey = GlobalKey();
String _globalTappedButtonId = 'teachersButton';
class FiltersAppBarSegment extends StatefulWidget {
@override
_FiltersAppBarSegmentState createState() => _FiltersAppBarSegmentState();
}
class _FiltersAppBarSegmentState extends State<FiltersAppBarSegment> {
List<Widget> buildStackChildren(SegmentChangedCallBack handleSegmentChanged) {
if (_globalTappedButtonId == 'teachersButton') {
return <Widget>[
Container(
key: UniqueKey(),
child: _Button(
key: studentsButtonKey,
id: 'studentsButton',
label: 'seeStudents',
rightPosition: 1,
onSegmentChanged: handleSegmentChanged,
),
),
Container(
key: UniqueKey(),
child: _Button(
key: teachersButtonKey,
id: 'teachersButton',
label: 'amTeacher',
rightPosition: null,
onSegmentChanged: handleSegmentChanged,
),
),
];
} else {
return <Widget>[
Container(
key: UniqueKey(),
child: _Button(
key: driverButtonKey,
id: 'driverButton',
label: 'amDriver',
rightPosition: null,
onSegmentChanged: handleSegmentChanged,
),
),
Container(
key: UniqueKey(),
child: _Button(
key: studentsButtonKey,
id: 'studentButton',
label: 'amStudent',
rightPosition: 1,
onSegmentChanged: handleSegmentChanged,
),
),
];
}
}
void handleSegmentChanged(String clickedButtonId) {
teachersButtonKey.currentState._handleButtonTapped();
studentsButtonKey.currentState._handleButtonTapped();
}
@override
Widget build(BuildContext context) {
return Container(
height: 42,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Stack(children: buildStackChildren(handleSegmentChanged)),
);
}
}
class _Button extends StatefulWidget {
final String id;
final String label;
final double rightPosition;
final void onSegmentChanged;
_Button({
Key key,
this.id,
this.label,
this.rightPosition,
this.onSegmentChanged,
}) : super(key: key);
@override
_ButtonState createState() => _ButtonState();
}
class _ButtonState extends State<_Button> {
bool _tapped;
double _topPosition;
double _width;
double _height;
double _getTopPosition() => _tapped ? 0 : 5;
double _getHeight() => _tapped ? 42 : 32;
Gradient _getGradient() {
if (_tapped) {
return Styles.darkAccentColorGradient;
} else {
return Styles.darkAccentColorGradientDisabled;
}
}
void _handleButtonTapped() {
setState(() {
_globalTappedButtonId = widget.id;
_tapped = (widget.id == _globalTappedButtonId);
_topPosition = _getTopPosition();
_height = _getHeight();
});
}
@override
void initState() {
super.initState();
_tapped = (widget.id == _globalTappedButtonId);
_topPosition = _getTopPosition();
_height = _getHeight();
}
@override
Widget build(BuildContext context) {
return Positioned(
top: _topPosition,
right: widget.rightPosition,
child: GestureDetector(
onTap: () {
widget.onSegmentChanged('test');
},
child: AnimatedContainer(
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
width: _width,
height: _height,
decoration: BoxDecoration(
gradient: _getGradient(),
borderRadius: BorderRadius.circular(13),
),
child: Center(
child: Text(
AppLocalizations.of(context).translate(widget.label),
style: Styles.bodyWhiteText,
textAlign: TextAlign.center,
),
),
),
),
);
}
}