0

我正在尝试在颤振中创建自己的自定义细分。该部分有两个按钮,一个用于教师,另一个用于学生。我正在尝试做的是将按钮封装在一个有状态的小部件中以处理两个按钮的 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,
            ),
          ),
        ),
      ),
    );
  }
}

4

1 回答 1

0

我确定您现在已经找到了解决问题的方法,但是这个问题是查看此错误时的第一个搜索结果之一。

如您所知,根据Flutter文档GlobalKey

“你不能同时在树中包含两个具有相同全局键的小部件。尝试这样做将在运行时断言。”

您可以定义自己的个人密钥,例如:

import 'package:flutter/widgets.dart';

class TestKeys{
  static final testKey1 = const Key('__TESTKEY1__');
  static final testKey2 = const Key('__TESTKEY2__');
  ...
}

然后在小部件中引用它们key: TestKeys.testKey1

这在此问题中进行了描述,因此也许它可以帮助需要类似用例的人。

此 GitHub 问题中还列出了一些解决方案

于 2020-07-13T12:58:07.463 回答