что такое _animation.value в анимации на Flutter?

Что такое _animation.value в анимации на Flutter и почему значение 260.0 вместо 1.0?

lowerBound - начальное значение анимации, в моем примере 0.0

upperBound - конечное значение анимации, в моем примере 1.0

value - текущее значение анимации, по умолчанию равно начальному значению lowerBound, т.е 0.0 в моем примере. Здесь все совпадает.

Теоретически, как я думал, value текущее значение анимации, должно находиться в пределах 0.0 и 0.1 включительно. На этом ошибочном выводе, я решил изменить opacity(непрозрачность) во время движения квадрата. В начале анимации прозрачность 0.0, в конце анимации прозрачность 1.0. НО ВО ВРЕМЯ ВСЕЙ АНИМАЦИИ ПРОЗРАЧНОСТЬ НУЛЕВАЯ

_color = Color.fromRGBO(255, 255, 255, _animation.value);

Я решил измерить значение текущей анимации, при движении квадрата, будет выводиться значения. В начале анимации значение 0.0, а вот в конце значение 260.0, а должно быть теоретически 1.0

Этот код был помещен в слушатель addListener(), вызывается при изменении текущего значения анимации value или при каждом тике объекта TickerProvider, здесь я точно не знаю.<br/

..addListener(() {
   setState(() {
    //
    _color = Color.fromRGBO(255, 255, 255, _animation.value);
    _str = '${_animation.value}';
    //идентично
    //_str = '${_controller.value}';
   });
  })

Далее скриншот, где значение 260.0 введите сюда описание изображения

Далее, полный код

main.dart

import 'dart:ui';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'Name App',
   theme: ThemeData(
    primarySwatch: Colors.blue,
   ),
   home: Scaffold(
    appBar: AppBar(
     title: Text('Name Page'),
    ),
    body: MyHomePage(),
   ),
  );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState
 extends State<MyHomePage>
 with SingleTickerProviderStateMixin {

 AnimationController _controller;
 Tween _tween;
 Animation<double> _animation;

 double _width;
 double _height;
 Color _color;

 String _str;

 @override
 void initState() {
  super.initState();

  _width = 100.0;
  _height = 100.0;
  _color = Colors.black38;

  _str = '';

  _controller = AnimationController(
   vsync: this,
   value: 0.0,      //default
   lowerBound: 0.0, //default
   upperBound: 1.0, //default
   duration: Duration(seconds: 1),
  )..addListener(() {
   setState(() {
    //
    _color = Color.fromRGBO(255, 255, 255, _animation.value);
    _str = '${_animation.value}';
    //идентично
    //_str = '${_controller.value}';
   });
  });

  _tween = Tween<double>(begin: 0.0, end: window.physicalSize.width / 2 - _width);

  _animation = _tween.animate(_controller);

 }

 @override
 void dispose() {
  super.dispose();
  _controller.dispose();
 }

 void _f1() {
  setState(() {

  });
 }

 void _funForward() {
  setState(() {
   _controller
    ..forward();
  });
 }

 void _funReverse() {
  setState(() {
   _controller
    ..reverse();
  });
 }

 @override
 Widget build(BuildContext context) {
  return Column(
   children: <Widget>[
    Expanded(
     flex: 1,
     child: LayoutBuilder(
      builder: (context, constraints) =>
       Stack(
        children: <Widget>[
         Positioned(
          // 1/2 высоты родительского - 1/2 высоты дочернего виджета
          top: (constraints.maxHeight / 2) - (_height / 2),
          left: _animation.value,
          child: Container(
           width: _width,
           height: _height,
           color: _color,
           alignment: Alignment.center,
           child: Text(
            _str,
            style: TextStyle(
             fontSize: 20.0,
             color: Colors.pink,
            ),
           ),
          ),
         ),
        ],
       ),
     ),
    ),
    Container(
     padding: const EdgeInsets.all(8.0),
     color: Colors.orangeAccent,
     child: Row(
      children: <Widget>[
       Expanded(
        flex: 1,
        child: RaisedButton(
         onPressed: () { _funForward(); },
         splashColor: Colors.blue.withOpacity(0.5),
         shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10)
         ),
         child: Text(
          'start'.toUpperCase(),
          style: TextStyle(
           color: Colors.deepPurple,
           fontSize: 16.0,
          ),
         ),
        ),
       ),
       SizedBox(width: 8.0,),
       Expanded(
        flex: 1,
        child: RaisedButton(
         onPressed: () { _funReverse(); },
         splashColor: Colors.blue.withOpacity(0.5),
         shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10)
         ),
         child: Text(
          'back'.toUpperCase(),
          style: TextStyle(
           color: Colors.deepPurple,
           fontSize: 16.0,
          ),
         ),
        ),
       ),
      ],
     ),
    ),
   ],
  );
 }

}

Ответы (1 шт):

Автор решения: MiT

_animation.value это текущее значение анимации.

В начале анимации значение 0.0, а вот в конце значение 260.0, а должно быть теоретически 1.0

Не должно вы переделали animation через tween:

_animation = _tween.animate(_controller);

А tween у вас:

_tween = Tween<double>(begin: 0.0, end: window.physicalSize.width / 2 - _width); // от 0.0 до размера середины экрана (у вас получается 260.0)

Чтобы все починить, достаточно использовать controller вместо animation:

..addListener(() {
   setState(() {
    //
    _color = Color.fromRGBO(255, 255, 255, _controller.value);
    _str = '${_animation.value}';
    // не идентично!
    // _str = '${_controller.value}';
   });
});
→ Ссылка