滚动时动画化小部件的位置

时间:2018-06-23 06:14:58

标签: android animation dart flutter

我正在尝试根据用户的滚动和滚动小部件(CustomScrollView内的位置来为应用中的小部件制作动画。

到目前为止,我将使用下面将要展示的方法实现一些看起来非常不错的效果,但是我担心这种特定方法:

  1. 就性能和资源而言,它不是最有效的。
  2. 不是最平滑的动画,导致动画不流畅。
  3. 在所有设备和分辨率上都不一致。

这是我想要实现的,请注意文本的位置,以及左下角的滚动页面指示符:

The animations

我通过以下步骤实现了它:

  1. 创建一个函数(_offsetPosition),该函数获取当前偏移量,小部件所属页面的索引,设备的视口尺寸以及我用来加快或降低速度的系数动画。该函数将返回-1.0到1.0之间的值,而-1.0在页面显示之前直到屏幕上显示的那一刻,-1.0消失时才是1.0,而页面填满我的视口时才是0.0。

  2. ScrollController的侦听器内部使用该函数,并根据滚动和我定义的其他常量更改变量的值,以使其根据我的需要进行更改。

  3. 将该变量用作我的窗口小部件的Padding(或其他任何参数,例如Opacity)。

这是_offsetPosition函数:

double _offsetPosition(double currentOffset, int pageIndex,
    double viewportDimension, double coefficient) {
  // Returns a value between -1.0 (left edge and before) to 1.0 (right edge and after).
  // 1.0 when the page fills the viewport exactly.
  // Making sure the return value won't be below -1.0 or 1.0 to avoid errors.
  double position = (currentOffset - pageIndex * viewportDimension) *
      coefficient /
      viewportDimension;

  if (position <= -1.0) {
    return -1.0;
  } else if (position >= 1.0) {
    return 1.0;
  } else {
    return position;
  }
}

这是我在initState内部定义的侦听器,用于在变量更改时更改变量值并在屏幕上build

void initState() {
  super.initState();

  _scrollController.addListener(() {
    setState(() {
      _pagePosition = _scrollController.offset /
          _scrollController.position.viewportDimension;

      _bg1Parallax = 0.2 -
          _offsetPosition(_scrollController.offset, 0,
                  _scrollController.position.viewportDimension, 1.0) *
              0.4;

      _bg2Parallax = 0.2 -
          _offsetPosition(_scrollController.offset, 1,
                  _scrollController.position.viewportDimension, 1.0) *
              0.4;

      _text1Padding = _offsetPosition(_scrollController.offset, 0,
              _scrollController.position.viewportDimension, 1.0) *
          1000.0;

      _text1Opacity = max(
          0.0,
          1.0 -
              _offsetPosition(_scrollController.offset, 0,
                      _scrollController.position.viewportDimension, 3.0)
                  .abs());
    });
  });
}

以下是文本和图标小部件在用户滚动时移动的示例,因为_pagePosition_text1Padding的值在用户向前滚动时会增加,反之亦然:

图标小部件:

new Padding(
  padding:
      new EdgeInsets.only(left: _pagePosition * 20.0),
  child: new Padding(
    padding: new EdgeInsets.all(0.0),
    child: new Icon(
      FontAwesomeIcons.circle,
      size: 15.0,
      color: Colors.white,
    ),
  ),
)

文本小部件:

new Padding(
  padding: new EdgeInsets.only(bottom: _text1Padding),
  child: new Center(
    child: new Opacity(
      opacity: _text1Opacity,
      child: new Text(
        'Text',
        style: new TextStyle(
            fontSize: 100.0, color: Colors.white),
      ),
    ),
  ),
)

TL; DR

我是否应该使用根据ScrollController偏移量而变化的值作为Padding参数来设置小部件位置的动画?

1 个答案:

答案 0 :(得分:0)

您是否尝试在真实设备上以发布模式运行应用?

通常,在滚动位置更改时重建窗口小部件树应该不是问题,因为Flutter的构建是为了有效地处理它(不重建底层的沉重的PASS __tests__\dummy.test.js ● Console console.log __tests__\dum my.test.js:13 [Function: onPress] 树)。

另一种方法是使用自定义RenderObjectas demonstrated in the flutter_gallery example application。您可以在Google Play上下载该应用程序(在应用程序中,选择研究>动画)。

我录制了一段动画视频: https://i.imgur.com/Pj9x09q.mp4