Как использовать два глобальных ключа для двух виджетов с общим классом состояния - PullRequest
0 голосов
/ 02 марта 2020

Я пытаюсь создать свой собственный сегмент в флаттере. Этот сегмент имеет две кнопки, одну для учителей и другую для студентов. То, что я пытаюсь сделать, это инкапсулировать кнопки в одном 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,
            ),
          ),
        ),
      ),
    );
  }
}

...