视差效果| 颤动的可滚动背景图像

帕妮·里维维

我正在尝试实现可滚动的背景图像(视差)。就像在主屏幕启动器中一样。

示例:在Evie启动器中:该视频

我试着用AnimatedBuilder提到这里在这样的文档。

我正在将ValueNotifier<double>用作AnimatedBuilder小部件的动画的侦听器。

完整的代码是这个

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PageView Scrolling',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
      home: HomePage(),
    );
  }
}

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

class _HomePageState extends State<HomePage>{
  ValueNotifier<double> _notifier;
  double _prevnotifier;

  double getOffset(){
    if (_notifier.value == 0 && _prevnotifier != null){
      return _prevnotifier;
    }
    return _notifier.value;
  }

  @override
  void dispose() {
    _notifier?.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _notifier = ValueNotifier<double>(0);
    _prevnotifier = _notifier.value;

    _notifier.addListener(
       (){
         print('object ${_notifier.value}');
           if (_notifier.value != 0)
             _prevnotifier = _notifier.value;
       }
    );
  }

  @override
  Widget build(BuildContext context) {
    print("Size is ${MediaQuery.of(context).size}");
    return Scaffold(
      body: Stack(
        children: <Widget>[
           AnimatedBuilder(
             animation: _notifier,
             builder: (context, _) {
               return Transform.translate(
                 offset: Offset(-getOffset() * 60, 0),
                 child: Image.network(
                   "https://w.wallhaven.cc/full/r2/wallhaven-r276qj.png",
                   height: MediaQuery.of(context).size.height,
                   fit: BoxFit.fitHeight
                 ),
               );
            },
          ),
          NotifyingPageView(
            notifier: _notifier,
          ),
        ],
      ),
    );
  }
}

class NotifyingPageView extends StatefulWidget {
  final ValueNotifier<double> notifier;

  const NotifyingPageView({Key key, this.notifier}) : super(key: key);

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

class _NotifyingPageViewState extends State<NotifyingPageView> {
  int _previousPage;
  PageController _pageController;

  void _onScroll() {
    // Consider the page changed when the end of the scroll is reached
    // Using onPageChanged callback from PageView causes the page to change when
    // the half of the next card hits the center of the viewport, which is not
    // what I want

    if (_pageController.page.toInt() == _pageController.page) {
      _previousPage = _pageController.page.toInt();
    }
    widget.notifier?.value = _pageController.page - _previousPage;
  }

  @override
  void initState() {
    _pageController = PageController(
       initialPage: 0,
       viewportFraction: 0.9,
     )..addListener(_onScroll);

     _previousPage = _pageController.initialPage;
     super.initState();
  }

  List<Widget> _pages = List.generate(
    10,
    (index) {
      return Container(
        height: 10,
        alignment: Alignment.center,
          color: Colors.transparent,
          child: Text(
            "Card number $index",
            style: TextStyle(
              color: Colors.teal,
              fontWeight: FontWeight.bold,
              fontSize: 25,
            ),
          ),
        );
      },
  );

  @override
  Widget build(BuildContext context) {
    return PageView(
      children: _pages,
      controller: _pageController,
    );
  }
}

图像可以在这里找到

现在我有两个问题:

  • 使用时图像fit: BoxFit.fitHeight没有完全溢出。目前是这样的
  • 由于动画完成后该值将变为零,因此它像这样捕捉:该视频

我试过在_notifier.value变成零之前存储值,并在它返回零时使用它,但这导致了上面视频中向您展示的怪异转换。

您认为可以做些什么来使像可滚动墙纸一样颤动?

像这样

设计

帕妮·里维维

这并不像我想的那么简单。

TLDR ; Github阅读了评论。

我使用了ValueNotifier<double>我提到的控件来控制滚动。

然后,与其Transform.translate使用我的属性。这是基于渲染前计算的OverflowBoxalignmentnotifier.value

并以全屏模式显示图像:

我曾经AspectRatio有个孩子DecoratedBox,其decorationBoxDecoration与它image作为ImageProvider

所有的代码,可以发现这里在GitHub上。(阅读评论)

这个问题在github上稍有详细信息,并通过一个不太复杂的替代实现安东内Galipò

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章