有同学在QQ群里面问怎么实现ListView下拉放大头部的效果。先放一张效果图
ezgif.com-resize.gif
实现这个效果的思路就是:
- 头部使用SizedBox
SizedBox(
width: screenWidth,
height: _getHeaderHeight(), // 动态修改 SizedBox 的高度
child: Container(
color: Colors.blueAccent,
child: FadeInImage.assetNetwork(
fadeInDuration: const Duration(milliseconds: 300),
placeholder: '',
image: 'https://static.flickr.com/225/505298484_1d04f2618e_o.jpg',
width: screenWidth,
height: _getHeaderHeight(),
fit: BoxFit.cover,
),
),
)
- 监听ListView的滑动,根据ListView滑动的 offset 动态改变 SizedBox 的高度
ListView.builder(
controller: _controller, // 使用ScrollController来监听ListView的滑动
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
)
根据ScrollController的offset来计算头部的高度
_scrollListener() {
setState(() {
_offset = _controller.offset;
});
}
double _getHeaderHeight() {
if (_offset == null) return headerHeight;
if (_offset <= 0) {
return min(max((headerHeight - _offset), headerHeight), 300.0);
}else {
return max(min((headerHeight - _offset), headerHeight), 50.0);
}
}
最后放上完整的代码:
import 'dart:math';
import 'package:flutter/material.dart';
class PullEffectListPage extends StatefulWidget {
@override
_PullEffectListPageState createState() => _PullEffectListPageState();
}
class _PullEffectListPageState extends State<PullEffectListPage> {
ScrollController _controller;
double _offset = 0.0;
final double headerHeight = 200.0;
_scrollListener() {
setState(() {
_offset = _controller.offset;
});
}
double _getHeaderHeight() {
if (_offset == null) return headerHeight;
if (_offset <= 0) {
return min(max((headerHeight - _offset), headerHeight), 300.0);
}else {
return max(min((headerHeight - _offset), headerHeight), 50.0);
}
}
@override
void initState() {
_controller = ScrollController();
_controller.addListener(_scrollListener);
super.initState();
}
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
title: Text('Pull Effect'),
),
body: Column(
children: <Widget>[
SizedBox(
width: screenWidth,
height: _getHeaderHeight(),
child: Container(
color: Colors.blueAccent,
child: FadeInImage.assetNetwork(
fadeInDuration: const Duration(milliseconds: 300),
placeholder: '',
image: 'https://static.flickr.com/225/505298484_1d04f2618e_o.jpg',
width: screenWidth,
height: _getHeaderHeight(),
fit: BoxFit.cover,
),
),
),
Expanded(
child: ListView.builder(
controller: _controller,
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
),
),
],
),
);
}
}
网友评论