赞
踩
前言:
关于吸顶效果,在Flutter当中,已经提供了这么一个控件,但是由于太复杂,所以网上的资料有些少,本文章主要利用Flutter自带的这种吸顶动画控件,配合着动画完成的一个用户中心的页面。
import 'package:flutter/material.dart'; class UserPage extends StatelessWidget { @override Widget build(BuildContext context) { double rpx = MediaQuery.of(context).size.width / 750; return Scaffold( body: MainPage(rpx: rpx,), ); } } class MainPage extends StatefulWidget { MainPage({Key key, this.rpx}); final double rpx; @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPage> with TickerProviderStateMixin { double extraPichHeight = 0; // 图片变化的高度 double prevdy; // 初始点击位置 BoxFit fitType; // 图片的适应方式 AnimationController animationcontroller; // 动画控制器 Animation<double> animation; // 动画 @override void initState() { super.initState(); prevdy = 0; fitType = BoxFit.fitWidth; animationcontroller = AnimationController(vsync: this, duration: Duration(milliseconds: 300)); // 动画时间 animation = Tween(begin: 0.0, end: 0.0).animate(animationcontroller); // 效果绑定动画时间 } // 手饰点击的时候执行 updatePicHeight(changed){ print('prevdy:$prevdy'); print('changed:$changed'); // 如果初始点击位置为0,那么记录传入进来的点击的值 // 如果之前没有点过,那么首次点击的位置就是手饰按下去的位置 if(prevdy == 0){ prevdy = changed; } //计算图片应该变化的高度 // 图片容器增长的高度 += 改变的高度坐标 - 鼠标上一个点的坐标(也就代表一直增长) extraPichHeight += changed - prevdy; // 如果下拉过了200后,就修改图片的适应格式 if(extraPichHeight >= 200 * widget.rpx){ fitType = BoxFit.fitHeight; }else{ fitType = BoxFit.fitWidth; } setState(() { prevdy = changed; extraPichHeight = extraPichHeight; fitType = fitType; }); } // 手饰抬起的时候执行 runAnimate(){ setState(() { animation = Tween(begin: extraPichHeight, end: 0.0).animate(animationcontroller)..addListener((){ if(extraPichHeight >= 200 * widget.rpx){ fitType = BoxFit.fitHeight; }else{ fitType = BoxFit.fitWidth; } setState(() { extraPichHeight = animation.value; fitType = fitType; }); }); // 执行完回弹之后,初始点击变化值 再次初始化为0(保证移动-鼠标位置 = 增长的高度) //(避免保留着上一次的鼠标点击值,造成下一次点击的时候,移动的高度比点击的位置小) prevdy = 0; }); } @override Widget build(BuildContext context) { double rpx = MediaQuery.of(context).size.width / 750; return Listener( onPointerMove: (result){ updatePicHeight(result.position.dy); }, onPointerUp: (_){ runAnimate(); animationcontroller.forward(from: 0); // }, child: CustomScrollView( physics: ClampingScrollPhysics(), slivers: <Widget>[ SliverAppBar( pinned: true, floating: true, leading: IconButton( icon: Icon(Icons.search), onPressed: (){}, ), expandedHeight: 500 * rpx + extraPichHeight, flexibleSpace: FlexibleSpaceBar( title: Text('用户中心'), centerTitle: true, background: SliverTopBar(extraPicHeight: extraPichHeight, fitType: fitType,), ), ), SliverList( delegate: SliverChildBuilderDelegate((context, index){ return Container(height: 30, color: Colors.blue,); }, childCount: 20) ) ], ), ); } } class SliverTopBar extends StatelessWidget { const SliverTopBar({Key key, @required this.extraPicHeight, @required this.fitType}); final double extraPicHeight; final BoxFit fitType; @override Widget build(BuildContext context) { double rpx = MediaQuery.of(context).size.width / 750; return Stack( children: <Widget>[ Column( children: <Widget>[ Image.asset( 'static/timg.jpg', width: 750 * rpx, height: 300 * rpx + extraPicHeight, fit: fitType, ), Container( height: 100 * rpx , ), Padding( padding: EdgeInsets.symmetric(horizontal:10.0), child: Divider( color: Colors.grey[700], ), ), Container( height: 100 * rpx, ), ], ), Positioned( top:250 * rpx + extraPicHeight, left: 35 * rpx, child: Container( width: 130 * rpx, height: 130 * rpx, child: CircleAvatar( backgroundImage: NetworkImage('http://b-ssl.duitang.com/uploads/item/201410/09/20141009224754_AswrQ.jpeg'), ), ), ) ], ); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。