在其外部调用小部件自身的功能

时间:2018-12-28 18:17:41

标签: function flutter statefulwidget

我有一个有状态的小部件,它可能处于两种情况,第一个是其中包含第一个文本的容器,例如“ Register”,第二个是带有不同文本的不同颜色的容器,用于例如“确认”。问题在于,这两种情况之间的过渡是使用动画完成的,例如,它不是实时逻辑:

color: isSituation1 ? Colors.blue : Colors.red.

实际上是这样的:

color: Color.lerp(Colors.blue, Colors.red, _animation1.value)  

还有一个功能,当用户点击转发动画控制器的容器时运行,就像这样:

_controller1.forward()

这是一个名为Button1

的小部件

因此,在“我的主页”状态小部件中,我还有另一个按钮应该触发Button1小部件中的逆过程,因此它将是:

_controller1.reverse()

我尝试在Button1小部件中创建一个函数,但是无法从外部运行它。如果可能的话我该怎么办?

2 个答案:

答案 0 :(得分:2)

因此,基本上,您想从另一个窗口小部件调用CustomWidget的方法。您可以定义ControllerClass,以便在创建CustomWidget的新实例时发出一个实例。该ControllerClass实例将保存CustomWidget的功能,并且您可以从外部调用它们。

通过一个示例,它是一个模态舍入式进度条,可以使用控制器类显示和隐藏。在此示例中,控制器类称为ProgressBarHandler。我不知道这是否是一种更好且正确的方法,但是可行。

class ModalRoundedProgressBar extends StatefulWidget {
  final String _textMessage;
  final double _opacity;
  final Color _color;
  final Function _handlerCallback;

  ModalRoundedProgressBar({
    @required Function handleCallback(ProgressBarHandler handler), //callback to get a controller
    String message = "",
    double opacity = 0.7,
    Color color = Colors.black54,
  })  : _textMessage = message,
        _opacity = opacity,
        _color = color,
        _handlerCallback = handleCallback;

  @override
  State createState() => _ModalRoundedProgressBarState();
}

class _ModalRoundedProgressBarState extends State<ModalRoundedProgressBar> {
  bool _isShowing = false;
  @override
  void initState() {
    super.initState();
    // init controller. 
    ProgressBarHandler handler = ProgressBarHandler();
    handler.show = this.show;
    handler.dismiss = this.dismiss;
    widget._handlerCallback(handler); // callback call.
  }

  @override
  Widget build(BuildContext context) {
    if (!_isShowing) return Stack();

    return Material(
      color: Colors.transparent,
      child: Stack(
        children: <Widget>[
          Opacity(
            opacity: widget._opacity,
            child: ModalBarrier(
              dismissible: false,
              color: Colors.black54,
            ),
          ),

          Center(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                CircularProgressIndicator(),
                Text(widget._textMessage),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void show() {
    setState(() => _isShowing = true);
  }

  void dismiss() {
    setState(() => _isShowing = false);
  }
}

  class ProgressBarHandler { 
      Function show; // will point to widget show method
      Function dismiss; // will point to another method.
   }


// ...in another external widget you can do...
// ... code your things and:
var controller;
var progressBar = ModalRoundedProgressBar(
  handleCallback: ((handler){ controller = handler; } ),);

//calling show method with controller
RaisedButton(
    onPressed: () { controller.show(); }
);


//calling dismiss method with controller
RaisedButton(
    onPressed: () { controller.dismiss(); }
);

答案 1 :(得分:0)

有可能,但是您可能不想这样做。您应该从父级提供AnimationController或构建应用程序以防止此类行为。无论如何,如果您仍然想这样,这里就可以了。

class HomePage extends StatefulWidget {
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  VoidCallback _reverseAnimation;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RaisedButton(
            child: Text('Reverse animation'),
            onPressed: () => _reverseAnimation(),
          ),
          Button1((controller) => _reverseAnimation = controller),
        ],
      ),
    );
  }
}

class Button1 extends StatefulWidget {
  final ValueChanged<VoidCallback> callback;
  Button1(this.callback);
  _Button1State createState() => _Button1State();
}

class _Button1State extends State<Button1> with SingleTickerProviderStateMixin {
  AnimationController _someAnimationController;

  void _reverseAnimation() {
    _someAnimationController?.reverse();
  }

  @override
  void initState() {
    super.initState();
    if (widget.callback != null) {
      widget.callback(_reverseAnimation);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Start animation'),
        onPressed: () => _someAnimationController.forward(),
      ),
    );
  }
}