问题描述
我正在尝试在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的数字在正数和负数之间切换,并更改视差的方向。