Flutter中平铺图像的偏移原点

问题描述

我正在尝试在Flutter应用程序中创建视差背景,最有效的构建方法是使用{% if url == 'user-posts' %} "Some HTML h1 tag I want do be shown only when this template is accessed via 'user-posts' url" {% endif %} ,将图像填充屏幕作为背景,然后将我的列表放在顶部。在Y轴上使用Stack设置平铺图像。然后计划与我用于列表的ImageRepeat同步,以平铺图块的原点。然后,我可以调整平铺图像的原点以创建视差效果。它应该真的很简单。这是上下文的一些代码

ScrollController

我的问题是图像没有Stack( children: [ SizedBox.expand( child: Image( image: Assetimage('assets/images/tiled_background_leaf.jpg'),repeat: ImageRepeat.repeatY,),CustomScrollView( controller: _controller,slivers: [ ... 属性offset位置。我需要一些有关最简单方法的建议。我已经看到有自定义的绘画工具,画布方法等,但是当在origin小部件中,或者可能在另一个将给我相同的小部件中应该有更优雅的解决方案时,它们似乎都过于复杂了。视差效果

解决方法

感谢@pskink给出答案(请参见上面的评论)。

以下是仪表板的一些代码,该仪表板具有文章滚动列表和视差滚动平铺图像作为背景...

class DashboardRoot extends StatefulWidget {
  DashboardRoot({Key key}) : super(key: key);

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

class _DashboardRootState extends State<DashboardRoot> {
  int _currentIndex = 0;
  ScrollController _controller;

  double _offsetY = 0.0;

  _scrollListener() {
    setState(() {
      _offsetY = _controller.offset;
    });
  }

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      var state = Provider.of<ArticlesState>(context,listen: false);
      state.initArticleStream();
    });
    _controller = ScrollController();
    _controller.addListener(_scrollListener);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        bottomNavigationBar: AppBottomNavigationBar(),body: Stack(
          children: [
            SizedBox.expand(
              child: Image(
                image: AssetImage('assets/images/tiled_background_leaf.jpg'),repeat: ImageRepeat.repeatY,alignment: FractionalOffset(0,(_offsetY / 1000) * -1),),CustomScrollView(
              controller: _controller,slivers: [
                SliverAppBar(
                  elevation: 0.0,floating: true,expandedHeight: 120,flexibleSpace: FlexibleSpaceBar(
                    title: Text(NavigationManager
                        .instance.menuItems[_currentIndex].title),actions: <Widget>[
                    IconButton(
                      icon: Icon(Icons.settings),onPressed: () => {
                        locator<NavigationService>()
                            .navigateTo(SettingsNavigator.routeName)
                      },IconButton(
                      icon: Icon(Icons.menu),onPressed: () => {RootScaffold.openDrawer(context)},],Consumer<ArticlesState>(
                  builder: (context,state,child) {
                    final List<Article> list = state.articles;
                    if (list == null) {
                      return SliverToBoxAdapter(
                        child: Center(
                          child: CircularProgressIndicator(
                              backgroundColor: Colors.amber,strokeWidth: 1),);
                    } else if (list.length > 0) {
                      return SliverGrid(
                        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                          maxCrossAxisExtent: 200.0,mainAxisSpacing: 10.0,crossAxisSpacing: 10.0,childAspectRatio: 1.0,delegate: SliverChildBuilderDelegate(
                          (BuildContext context,int index) {
                            Article article = list[index];
                            return ArticleCell(
                                article: article,cellTapHandler: () {
                                  Navigator.pushNamed(
                                      context,ArticleDetail.routeName,arguments: new ArticleDetailArguments(
                                          article.docId,article.heading));
                                });
                          },childCount: list.length,);
                    } else {
                      return Center(
                        child: Text("No Articles"),);
                    }
                  },));
  }
}

请注意,Stack的背景图像位于展开的SizedBox中,因此它会填满屏幕空间。上面的层是CustomScrollView,其中包含SliverGrid和其他内容。

重要的一点是Image

child: Image(
                image: AssetImage('assets/images/tiled_background_leaf.jpg'),

,还有_offsetY侦听器在用户滚动时设置的属性ScrollController

double _offsetY = 0.0;

  _scrollListener() {
    setState(() {
      _offsetY = _controller.offset;
    });
  }

Image对齐属性用于将对齐方式设置为顶部,中心,左侧等,但也可以是任意偏移量。 FractionalOffset值的范围是0..1,但将其设置为大于或小于零的较大数字也是绝对可以的。由于还使用ImageRepeat.repeatY对图像进行了平铺,因此使用对齐方式重新绘制了平铺图像的原点,并且通过弄乱数字,可以创建很好的视差滚动效果。

请注意,FractionalOffset(0,(_offsetY / 1000) * -1)的偏移值除以1000(这是您的速度,值越大,背景视差越慢(将其视作两层之间的距离)。 -1的数字在正数和负数之间切换,并更改视差的方向。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...