首页 > 解决方案 > 如何重用 Stateful Widget?

问题描述

我正在尝试制作一个简单的页面滑块。

这是 page 的样子:page,这是 transition 的样子:transition

initState我在中设置了随机颜色page widget

Widget _buildPages() {
    switch (_transitionType) {
      case TransitionType.none:
        return _currentPage;
      case TransitionType.sliding:
        return Stack(
          children: [
            AbsorbPointer(
              absorbing: _slideAnimationController.isAnimating,
              child: _currentPage,
            ),
            AbsorbPointer(
              absorbing: _slideAnimationController.isAnimating,
              child: SlideTransition(
                position: _slideAnimation,
                child: _nextPage,
              ),
            ),
          ],
        );
    }
  }

首字母_transitionTypenone。当我按下next按钮时,它变成sliding. 问题是我不能_currentPage以它的确切状态重用小部件(initState尽管我只创建了一次小部件然后只在其中重用它,但总是被调用_buildPages())。

请你帮助我好吗?

更新:完整代码:

enum TransitionType {
  none,
  sliding,
}

class PageSlider extends StatefulWidget {
  PageSlider({
    @required this.items,
  });

  final List<String> items;

  @override
  _PageSliderState createState() => _PageSliderState();
}

class _PageSliderState extends State<PageSlider> with TickerProviderStateMixin {
  AnimationController _slideAnimationController;
  Animation<Offset> _slideAnimation;
  int _currentIndex;
  TransitionType _transitionType;

  Widget _currentPage;
  Widget _nextPage;

  void _finishPageTransition() {
    setState(() {
      _currentIndex++;
      _currentPage = _nextPage;
      _transitionType = TransitionType.none;
      _slideAnimationController.value = 0.0;
    });
  }

  Widget _buildPages() {
    switch (_transitionType) {
      case TransitionType.none:
        return _currentPage;
      case TransitionType.sliding:
        return Stack(
          children: [
            AbsorbPointer(
              absorbing: _slideAnimationController.isAnimating,
              child: _currentPage,
            ),
            AbsorbPointer(
              absorbing: _slideAnimationController.isAnimating,
              child: SlideTransition(
                position: _slideAnimation,
                child: _nextPage,
              ),
            ),
          ],
        );
    }
  }

  void _goToNextPage() {
    if (_currentIndex < widget.items.length - 1) {
      setState(() {
        _nextPage = PageItem(
          item: widget.items[_currentIndex + 1],
          onNext: _goToNextPage,
        );
        _transitionType = TransitionType.sliding;
        _slideAnimationController.forward(from: 0.0).whenComplete(_finishPageTransition);
      });
    }
  }

  @override
  void initState() {
    super.initState();
    _slideAnimationController = AnimationController(
      duration: Duration(milliseconds: 1000),
      vsync: this,
    );

    _slideAnimation = Tween<Offset>(
      begin: Offset(1.0, 0.0),
      end: Offset.zero,
    ).animate(_slideAnimationController);

    _currentIndex = 0;
    _currentPage = PageItem(
      item: widget.items[_currentIndex],
      onNext: _goToNextPage,
    );
    _transitionType = TransitionType.none;

  }

  @override
  Widget build(BuildContext context) {
    return _buildPages();
  }
}

class PageItem extends StatefulWidget {
  PageItem({
    @required this.item,
    @required this.onNext,
    key,
  }) : super(key: key);

  final String item;
  final void Function() onNext;

  @override
  _PageItemState createState() => _PageItemState();
}

class _PageItemState extends State<PageItem> with TickerProviderStateMixin {
  Color _color;

  Color _getColor() {
    return Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1);
  }

  @override
  void initState() {
    super.initState();
    _color = _getColor();
    print('init ${widget.item}');
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Container(
        decoration: BoxDecoration(
          color: _color,
          border: Border.all(
            color: Colors.black,
            width: 1,
          ),
        ),
        child: SizedBox.expand(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              GestureDetector(
                onTap: () {
                  setState(() {
                    _color = _getColor();
                  });
                },
                child: Text(
                  widget.item,
                  style: TextStyle(
                    fontSize: 40,
                  ),
                ),
              ),
              CupertinoButton(
                color: CupertinoColors.activeBlue,
                child: Text('next'),
                onPressed: widget.onNext,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

标签: flutter

解决方案


我不确定我是否正在关注这个问题。但是,您是否尝试将 UniqueKey()/ValueKey() 传递给 _currentPage 小部件?


推荐阅读