Last active
August 8, 2024 12:21
-
-
Save arnaudruffin/6c2cdea6aa48de8f2ce6bd1f27e3049a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter/gestures.dart'; | |
/// Flutter code sample for [CarouselView]. | |
void main() => runApp(const CarouselExampleApp()); | |
class CarouselExampleApp extends StatelessWidget { | |
const CarouselExampleApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
scrollBehavior: AppScrollBehavior(), | |
home: Scaffold( | |
appBar: AppBar( | |
leading: const Icon(Icons.cast), | |
title: const Text('Flutter TV'), | |
actions: const <Widget>[ | |
Padding( | |
padding: EdgeInsetsDirectional.only(end: 16.0), | |
child: CircleAvatar(child: Icon(Icons.account_circle)), | |
), | |
], | |
), | |
body: const CarouselExample(), | |
), | |
); | |
} | |
} | |
class CarouselExample extends StatefulWidget { | |
const CarouselExample({super.key}); | |
@override | |
State<CarouselExample> createState() => _CarouselExampleState(); | |
} | |
class _CarouselExampleState extends State<CarouselExample> { | |
final CarouselController controller = CarouselController(initialItem: 1); | |
@override | |
void dispose() { | |
controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final double height = MediaQuery.sizeOf(context).height; | |
return ListView( | |
children: <Widget>[ | |
ConstrainedBox( | |
constraints: BoxConstraints(maxHeight: height / 2), | |
child: CarouselView.weighted( | |
controller: controller, | |
itemSnapping: true, | |
flexWeights: const <int>[1, 7, 1], | |
children: ImageInfo.values.map((ImageInfo image) { | |
return HeroLayoutCard(imageInfo: image); | |
}).toList(), | |
), | |
), | |
const SizedBox(height: 20), | |
const Padding( | |
padding: EdgeInsetsDirectional.only(top: 8.0, start: 8.0), | |
child: Text('Multi-browse layout'), | |
), | |
ConstrainedBox( | |
constraints: const BoxConstraints(maxHeight: 50), | |
child: CarouselView.weighted( | |
flexWeights: const <int>[1, 2, 3, 2, 1], | |
consumeMaxWeight: false, | |
children: List<Widget>.generate(20, (int index) { | |
return ColoredBox( | |
color: Colors.primaries[index % Colors.primaries.length] | |
.withOpacity(0.8), | |
child: const SizedBox.expand(), | |
); | |
}), | |
), | |
), | |
const SizedBox(height: 20), | |
ConstrainedBox( | |
constraints: const BoxConstraints(maxHeight: 200), | |
child: CarouselView.weighted( | |
flexWeights: const <int>[3, 3, 3, 2, 1], | |
consumeMaxWeight: false, | |
children: CardInfo.values.map((CardInfo info) { | |
return ColoredBox( | |
color: info.backgroundColor, | |
child: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
Icon(info.icon, color: info.color, size: 32.0), | |
Text(info.label, | |
style: const TextStyle(fontWeight: FontWeight.bold), | |
overflow: TextOverflow.clip, | |
softWrap: false), | |
], | |
), | |
), | |
); | |
}).toList()), | |
), | |
const SizedBox(height: 20), | |
const Padding( | |
padding: EdgeInsetsDirectional.only(top: 8.0, start: 8.0), | |
child: Text('Uncontained layout'), | |
), | |
ConstrainedBox( | |
constraints: const BoxConstraints(maxHeight: 200), | |
child: CarouselView( | |
itemExtent: 330, | |
shrinkExtent: 200, | |
children: List<Widget>.generate(20, (int index) { | |
return UncontainedLayoutCard(index: index, label: 'Show $index'); | |
}), | |
), | |
) | |
], | |
); | |
} | |
} | |
class HeroLayoutCard extends StatelessWidget { | |
const HeroLayoutCard({ | |
super.key, | |
required this.imageInfo, | |
}); | |
final ImageInfo imageInfo; | |
@override | |
Widget build(BuildContext context) { | |
final double width = MediaQuery.sizeOf(context).width; | |
return Stack( | |
alignment: AlignmentDirectional.bottomStart, | |
children: <Widget>[ | |
ClipRect( | |
child: OverflowBox( | |
maxWidth: width * 7 / 8, | |
minWidth: width * 7 / 8, | |
child: Image( | |
fit: BoxFit.cover, | |
image: NetworkImage( | |
'https://flutter.github.io/assets-for-api-docs/assets/material/${imageInfo.url}'), | |
), | |
), | |
), | |
Padding( | |
padding: const EdgeInsets.all(18.0), | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisSize: MainAxisSize.min, | |
children: <Widget>[ | |
Text( | |
imageInfo.title, | |
overflow: TextOverflow.clip, | |
softWrap: false, | |
style: Theme.of(context) | |
.textTheme | |
.headlineLarge | |
?.copyWith(color: Colors.white), | |
), | |
const SizedBox(height: 10), | |
Text( | |
imageInfo.subtitle, | |
overflow: TextOverflow.clip, | |
softWrap: false, | |
style: Theme.of(context) | |
.textTheme | |
.bodyMedium | |
?.copyWith(color: Colors.white), | |
) | |
], | |
), | |
), | |
]); | |
} | |
} | |
class UncontainedLayoutCard extends StatelessWidget { | |
const UncontainedLayoutCard({ | |
super.key, | |
required this.index, | |
required this.label, | |
}); | |
final int index; | |
final String label; | |
@override | |
Widget build(BuildContext context) { | |
return ColoredBox( | |
color: Colors.primaries[index % Colors.primaries.length].withOpacity(0.5), | |
child: Center( | |
child: Text( | |
label, | |
style: const TextStyle(color: Colors.white, fontSize: 20), | |
overflow: TextOverflow.clip, | |
softWrap: false, | |
), | |
), | |
); | |
} | |
} | |
enum CardInfo { | |
camera('Cameras', Icons.video_call, Color(0xff2354C7), Color(0xffECEFFD)), | |
lighting('Lighting', Icons.lightbulb, Color(0xff806C2A), Color(0xffFAEEDF)), | |
climate('Climate', Icons.thermostat, Color(0xffA44D2A), Color(0xffFAEDE7)), | |
wifi('Wifi', Icons.wifi, Color(0xff417345), Color(0xffE5F4E0)), | |
media('Media', Icons.library_music, Color(0xff2556C8), Color(0xffECEFFD)), | |
security( | |
'Security', Icons.crisis_alert, Color(0xff794C01), Color(0xffFAEEDF)), | |
safety( | |
'Safety', Icons.medical_services, Color(0xff2251C5), Color(0xffECEFFD)), | |
more('', Icons.add, Color(0xff201D1C), Color(0xffE3DFD8)); | |
const CardInfo(this.label, this.icon, this.color, this.backgroundColor); | |
final String label; | |
final IconData icon; | |
final Color color; | |
final Color backgroundColor; | |
} | |
enum ImageInfo { | |
image0('The Flow', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_1.png'), | |
image1('Through the Pane', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_2.png'), | |
image2('Iridescence', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_3.png'), | |
image3('Sea Change', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_4.png'), | |
image4('Blue Symphony', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_5.png'), | |
image5('When It Rains', 'Sponsored | Season 1 Now Streaming', | |
'content_based_color_scheme_6.png'); | |
const ImageInfo(this.title, this.subtitle, this.url); | |
final String title; | |
final String subtitle; | |
final String url; | |
} | |
class AppScrollBehavior extends MaterialScrollBehavior { | |
@override | |
Set<PointerDeviceKind> get dragDevices => { | |
PointerDeviceKind.touch, | |
PointerDeviceKind.mouse, | |
PointerDeviceKind.trackpad, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment