flutter 2 SliverPersistentHeader - 滚动期间避免重叠
flutter 2 SliverPersistentHeader - avoid overlap during scroll
这是我的代码:
import 'package:all_in_one/cooking/pages/recipe/header/search_bar_header.dart';
import 'package:all_in_one/cooking/pages/recipe/header/welcome_header.dart';
import 'package:flutter/material.dart';
class MyRecipePage extends StatefulWidget {
final String title;
MyRecipePage({Key? key, required this.title}) : super(key: key);
@override
_MyRecipePageState createState() => _MyRecipePageState();
}
class _MyRecipePageState extends State<MyRecipePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
WelcomeHeader(),
SearchBarHeader(),
SliverGrid.count(),
],
) ,
);
}
}
class WelcomeHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return
SliverPersistentHeader(
floating: true,
delegate: SliverAppBarDelegate(
minHeight: 0,
maxHeight: 100,
child: Container(
color: Colors.white,
child: _MyWelcomingHeader(),
),
),
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Enjoy the recipes',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
);
}
}
class SearchBarHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 50,
maxHeight: 50,
child: Container(
color: Colors.white,
child: _MySearchBar(),
),
),
);
}
}
class _MySearchBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(width: 10),
const Icon(Icons.search, color: Colors.grey, size: 30),
const SizedBox(width: 5),
Text("Search product",
style: TextStyle(
color: Colors.grey.shade500, fontSize: 12, fontWeight: FontWeight.w200))
],
);
}
}
银条Delegate的代码来自这个
import 'package:flutter/material.dart';
import 'dart:math' as math;
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
我的目标是有 2 个 SliverPersistentHeader
,一个固定,一个浮动。
浮动的(第一个)应该在滚动时调整文本和图像的大小..
在下面的屏幕截图中,我们可以看到第二个 SliverPersistentHeader
与第一个重叠。
我该怎么做才能使 Text
自行调整大小。我尝试像使用 CircleAvatar
一样使用 Flexible
但我无法成功:/
谢谢
我找到了一个使用不透明度的解决方案,所以我的 WelcomeHeader
变成了:
import 'package:flutter/material.dart';
import 'dart:math' as math;
class WelcomeHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverAppBar(
backgroundColor: Colors.white,
pinned: false,
floating: false,
snap: false,
expandedHeight: 120,
flexibleSpace: _MyWelcomingHeader()
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, c) {
final settings = context
.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
final deltaExtent = settings!.maxExtent - settings.minExtent;
final t =
(1.0 - (settings.currentExtent - settings.minExtent) / deltaExtent)
.clamp(0.0, 1.0);
final fadeStart = math.max(0.0, 1.0 - kToolbarHeight / deltaExtent);
const fadeEnd = 1.0;
final opacity = 1.0 - Interval(fadeStart, fadeEnd).transform(t);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Opacity(
opacity: opacity,
child: Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Enjoy the recipes !',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
});
}
}
这是我的代码:
import 'package:all_in_one/cooking/pages/recipe/header/search_bar_header.dart';
import 'package:all_in_one/cooking/pages/recipe/header/welcome_header.dart';
import 'package:flutter/material.dart';
class MyRecipePage extends StatefulWidget {
final String title;
MyRecipePage({Key? key, required this.title}) : super(key: key);
@override
_MyRecipePageState createState() => _MyRecipePageState();
}
class _MyRecipePageState extends State<MyRecipePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
WelcomeHeader(),
SearchBarHeader(),
SliverGrid.count(),
],
) ,
);
}
}
class WelcomeHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return
SliverPersistentHeader(
floating: true,
delegate: SliverAppBarDelegate(
minHeight: 0,
maxHeight: 100,
child: Container(
color: Colors.white,
child: _MyWelcomingHeader(),
),
),
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Enjoy the recipes',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
);
}
}
class SearchBarHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 50,
maxHeight: 50,
child: Container(
color: Colors.white,
child: _MySearchBar(),
),
),
);
}
}
class _MySearchBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(width: 10),
const Icon(Icons.search, color: Colors.grey, size: 30),
const SizedBox(width: 5),
Text("Search product",
style: TextStyle(
color: Colors.grey.shade500, fontSize: 12, fontWeight: FontWeight.w200))
],
);
}
}
银条Delegate的代码来自这个
import 'package:flutter/material.dart';
import 'dart:math' as math;
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
我的目标是有 2 个 SliverPersistentHeader
,一个固定,一个浮动。
浮动的(第一个)应该在滚动时调整文本和图像的大小..
在下面的屏幕截图中,我们可以看到第二个 SliverPersistentHeader
与第一个重叠。
我该怎么做才能使 Text
自行调整大小。我尝试像使用 CircleAvatar
一样使用 Flexible
但我无法成功:/
谢谢
我找到了一个使用不透明度的解决方案,所以我的 WelcomeHeader
变成了:
import 'package:flutter/material.dart';
import 'dart:math' as math;
class WelcomeHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverAppBar(
backgroundColor: Colors.white,
pinned: false,
floating: false,
snap: false,
expandedHeight: 120,
flexibleSpace: _MyWelcomingHeader()
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, c) {
final settings = context
.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
final deltaExtent = settings!.maxExtent - settings.minExtent;
final t =
(1.0 - (settings.currentExtent - settings.minExtent) / deltaExtent)
.clamp(0.0, 1.0);
final fadeStart = math.max(0.0, 1.0 - kToolbarHeight / deltaExtent);
const fadeEnd = 1.0;
final opacity = 1.0 - Interval(fadeStart, fadeEnd).transform(t);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Opacity(
opacity: opacity,
child: Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Enjoy the recipes !',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
});
}
}