Использование SliverPersistentHeader без этого заголовка сжимается, но просто исчезает во Flutter Web
Я создаю веб-сайт и хотел бы иметь SliverAppBar или SliverPersistentHeader с каруселью изображений. Это я вполне могу сделать, но я не хочу, чтобы карусель изображений сжималась при прокрутке вниз. Вместо этого я бы хотел, чтобы SliverAppBar исчез, но без уменьшения ширины, а вместо этого просто уменьшилась высота. Надеюсь, моя проблема ясна. Если есть вопросы, задавайте. Вот мой код:
import 'package:flutter/material.dart';
import 'package:flutter_app/Widgets/HomePageWidgets/ImageCarousel.dart';
import '../Widgets/GlobalWidgets/TopNavBar.dart';
//import 'package:flutter_app/Widgets/HomePageWidgets/HomePageImage.dart';
import '../Widgets/GlobalWidgets/BottomBar.dart';
import '../Widgets/HomePageWidgets/ImageCarousel.dart';
import '../Widgets/GlobalWidgets/OneCard.dart';
import '../Widgets/GlobalWidgets/TwoCards.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
return Material(
child: Container(
child: CustomScrollView (
slivers: [
// HomePageImage(), //wurde durch ImageCarousel() ersetzt
SliverAppBar(
expandedHeight: screenSize.height * 0.9,
backgroundColor: Colors.white.withOpacity(1),
flexibleSpace: ImageCarousel(), // AUTOPLAY MUSS ANGESTELLT WERDEN,
),
SliverList(delegate: SliverChildListDelegate([
//ImageCarousel(), // AUTOPLAY MUSS ANGESTELLT WERDEN
Expanded(
child: Container(
child: Row(
// Die Row mache ich nur hin, damit ich die Seite zentrieren kann. Wenn alles nach links soll, dann einfach Row entfernen
mainAxisAlignment: MainAxisAlignment.center,
children: [
TopNavBar(),
],
),
),
), //TopNavBar // TODO 1: DropDownButton muss noch erstellt werden // TODO 2: Funktionen zu den Buttons müssen hinzufügt werden
OneCard(),
Container(height: 1000,
width: 500,),
BottomBar(), // TODO 3: Funktionen zu den Buttons müssen hinzufügt werden
]))
],
),
),
);
}
}
Это моя карусель изображений:
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';
// https://pub.dev/packages/carousel_slider Link zum Package
class ImageCarousel extends StatefulWidget {
@override
_ImageCarouselState createState() => _ImageCarouselState();
}
class _ImageCarouselState extends State<ImageCarousel> {
List imgList = [
'assets/images/Mathildedoppelt.jpeg',
'assets/images/reveuse2.jpeg',
];
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
final double height = MediaQuery.of(context).size.height;
return CarouselSlider(
options: CarouselOptions(
height: screenSize.height * 0.9, //Ich kann hier einfach * 1.2 rechnen und dann füllt es den ganzen Bildschirm aus
aspectRatio: 16/9,
viewportFraction: 1,
initialPage: 0,
enableInfiniteScroll: true,
reverse: false,
autoPlay: false, // AUTOPLAY MUSS UNBEDINGT AN
autoPlayInterval: Duration(seconds: 6),
autoPlayAnimationDuration: Duration(seconds: 3),
enlargeCenterPage: false,
scrollDirection: Axis.horizontal,
),
items: imgList
.map((item) => Container(
child: Center(
child: Image.network(
item,
fit: BoxFit.cover,
height: height,
)),
))
.toList(),
);
}
}
Это код с SliverPersistentHeader:
import 'package:flutter/material.dart';
import 'package:flutter_app/Widgets/HomePageWidgets/ImageCarousel.dart';
import '../Widgets/GlobalWidgets/TopNavBar.dart';
//import 'package:flutter_app/Widgets/HomePageWidgets/HomePageImage.dart';
import '../Widgets/GlobalWidgets/BottomBar.dart';
import '../Widgets/HomePageWidgets/ImageCarousel.dart';
import '../Widgets/GlobalWidgets/OneCard.dart';
import '../Widgets/GlobalWidgets/TwoCards.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
return Material(
child: Container(
child: CustomScrollView (
slivers: [
// HomePageImage(), //wurde durch ImageCarousel() ersetzt
/*SliverAppBar(
expandedHeight: screenSize.height * 0.9,
backgroundColor: Colors.white.withOpacity(1),
flexibleSpace: ImageCarousel(), // AUTOPLAY MUSS ANGESTELLT WERDEN,
),*/
SliverPersistentHeader(
delegate: MyDynamicHeader(),
),
SliverList(delegate: SliverChildListDelegate([
//ImageCarousel(), // AUTOPLAY MUSS ANGESTELLT WERDEN
Expanded(
child: Container(
child: Row(
// Die Row mache ich nur hin, damit ich die Seite zentrieren kann. Wenn alles nach links soll, dann einfach Row entfernen
mainAxisAlignment: MainAxisAlignment.center,
children: [
TopNavBar(),
],
),
),
), //TopNavBar // TODO 1: DropDownButton muss noch erstellt werden // TODO 2: Funktionen zu den Buttons müssen hinzufügt werden
OneCard(),
SizedBox(height: 20,),
TwoCards(),
Container(height: 1000,
width: 500,),
BottomBar(), // TODO 3: Funktionen zu den Buttons müssen hinzufügt werden
]))
],
),
),
);
}
}
class MyDynamicHeader extends SliverPersistentHeaderDelegate {
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return ImageCarousel();
}
@override
bool shouldRebuild(SliverPersistentHeaderDelegate _) => true;
@override
double get maxExtent => 650.0;
@override
double get minExtent => 0.0;
}
1 ответ
В свопинге не хватает одной вещи: при свопинге будет отображаться только полное изображение, например, при обмене 2 изображения на экране. Но функция анимации не работает для
Демо-код:
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
class CustomSS extends StatefulWidget {
CustomSS({Key? key}) : super(key: key);
@override
_CustomSSState createState() => _CustomSSState();
}
class _CustomSSState extends State<CustomSS> {
final CarouselController controller = CarouselController();
final imageList = [
'assets/me.jpg',
'assets/ocean.jpg',
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: _ImageCarouselState(
controller: controller,
imgList: imageList,
size: Size(
constraints.maxWidth,
constraints.maxHeight * .4,
),
),
),
Positioned(
child: SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth,
child: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate(
[
///ToolBar
SizedBox(
height: constraints.maxHeight * .4 + kToolbarHeight,
child: GestureDetector(
onHorizontalDragEnd: (details) {
if (details.primaryVelocity! > 0) {
controller.previousPage();
}
// Swiping in left direction.
else if (details.primaryVelocity! < 0.0) {
controller.nextPage();
}
},
),
),
Column(
children: List.generate(
122,
(index) => Container(
height: 100,
width: constraints.maxWidth,
color:
index.isEven ? Colors.red : Colors.yellow,
),
),
),
],
),
)
],
),
),
),
],
),
),
);
}
}
class _ImageCarouselState extends StatelessWidget {
final Size size;
final List imgList;
final CarouselController controller;
_ImageCarouselState({
Key? key,
required this.size,
required this.controller,
required this.imgList,
}) : super(key: key);
@override
Widget build(
BuildContext context,
) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
CarouselSlider(
carouselController: controller,
options: CarouselOptions(
height: size.height,
// height: screenSize.height *
// 0.9, //Ich kann hier einfach * 1.2 rechnen und dann füllt es den ganzen Bildschirm aus
aspectRatio: 16 / 9,
viewportFraction: 1,
initialPage: 0,
enableInfiniteScroll: true,
reverse: false,
// autoPlay: true, // AUTOPLAY MUSS UNBEDINGT AN
// autoPlayInterval: Duration(seconds: 1),
// autoPlayAnimationDuration: Duration(seconds: 1),
enlargeCenterPage: false,
// scrollDirection: Axis.horizontal,
),
items: imgList
.map((item) => Container(
width: size.width,
child: Center(
child: Image.network(
item,
fit: BoxFit.cover,
)),
))
.toList(),
),
Container(
height: kToolbarHeight,
color: Colors.cyanAccent,
width: size.width,
child: Row(
children: [
Text(
"TabBar",
),
Text(
"Or others",
),
Text(
"Items",
),
],
),
)
],
);
}
}