diff --git a/_config.yml b/_config.yml index 6381be18ce2..0d4808b29c4 100644 --- a/_config.yml +++ b/_config.yml @@ -17,9 +17,10 @@ repo: flutter: https://github.com/flutter/flutter samples: https://github.com/flutter/samples packages: https://github.com/flutter/packages - gallery: https://github.com/flutter/gallery + gallery-archive: https://github.com/flutter/gallery engine: https://github.com/flutter/engine uxr: https://github.com/flutter/uxr + wonderous: https://github.com/gskinnerTeam/flutter-wonderous-app dart: api: https://api.dart.dev sdk: @@ -39,7 +40,7 @@ pub-pkg: https://pub.dev/packages flutter-medium: https://medium.com/flutter medium: https://medium.com dartpad: https://dartpad.dev -gallery: https://gallery.flutter.dev +gallery-archive: https://flutter-gallery-archive.web.app material: https://m3.material.io material2: https://m2.material.io so: https://stackoverflow.com @@ -52,6 +53,7 @@ developers: https://developers.google.com codelabs: https://codelabs.developers.google.com groups: https://groups.google.com firebase: https://firebase.google.com +wonderous: https://wonderous.app/ youtube-site: https://youtube.com ## Software minimum versions diff --git a/examples/layout/gallery/README.md b/examples/layout/gallery/README.md new file mode 100644 index 00000000000..7ada6c5be60 --- /dev/null +++ b/examples/layout/gallery/README.md @@ -0,0 +1,8 @@ +Examples referenced in +["Layouts in Flutter"](https://docs.flutter.dev/ui/layout) that come from +the now-archived [Flutter Gallery](https://docs.flutter.dev/gallery). +They are mostly the same with a few updates to run standalone, +use new language features, and follow modern Dart/Flutter style. + +These should eventually be updated, replaced, removed, or similar +as the layout documentation is rewritten. diff --git a/examples/layout/gallery/analysis_options.yaml b/examples/layout/gallery/analysis_options.yaml new file mode 100644 index 00000000000..eee60e0f5a2 --- /dev/null +++ b/examples/layout/gallery/analysis_options.yaml @@ -0,0 +1,5 @@ +# Take our settings from the example_utils analysis_options.yaml file. +# If necessary for a particular example, this file can also include +# overrides for individual lints. + +include: package:example_utils/analysis.yaml diff --git a/examples/layout/gallery/assets/demos/bottom_navigation_background.png b/examples/layout/gallery/assets/demos/bottom_navigation_background.png new file mode 100644 index 00000000000..868402f9db4 Binary files /dev/null and b/examples/layout/gallery/assets/demos/bottom_navigation_background.png differ diff --git a/examples/layout/gallery/assets/places/india_chennai_flower_market.png b/examples/layout/gallery/assets/places/india_chennai_flower_market.png new file mode 100644 index 00000000000..df08f74ff9c Binary files /dev/null and b/examples/layout/gallery/assets/places/india_chennai_flower_market.png differ diff --git a/examples/layout/gallery/assets/places/india_chennai_highway.png b/examples/layout/gallery/assets/places/india_chennai_highway.png new file mode 100644 index 00000000000..a7343a329a7 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_chennai_highway.png differ diff --git a/examples/layout/gallery/assets/places/india_chettinad_produce.png b/examples/layout/gallery/assets/places/india_chettinad_produce.png new file mode 100644 index 00000000000..c04f6e879bb Binary files /dev/null and b/examples/layout/gallery/assets/places/india_chettinad_produce.png differ diff --git a/examples/layout/gallery/assets/places/india_chettinad_silk_maker.png b/examples/layout/gallery/assets/places/india_chettinad_silk_maker.png new file mode 100644 index 00000000000..afabb4f0e9e Binary files /dev/null and b/examples/layout/gallery/assets/places/india_chettinad_silk_maker.png differ diff --git a/examples/layout/gallery/assets/places/india_pondicherry_beach.png b/examples/layout/gallery/assets/places/india_pondicherry_beach.png new file mode 100644 index 00000000000..0f2c0f6029a Binary files /dev/null and b/examples/layout/gallery/assets/places/india_pondicherry_beach.png differ diff --git a/examples/layout/gallery/assets/places/india_pondicherry_fisherman.png b/examples/layout/gallery/assets/places/india_pondicherry_fisherman.png new file mode 100644 index 00000000000..c2c4b936075 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_pondicherry_fisherman.png differ diff --git a/examples/layout/gallery/assets/places/india_pondicherry_salt_farm.png b/examples/layout/gallery/assets/places/india_pondicherry_salt_farm.png new file mode 100644 index 00000000000..0f09ec5a0b4 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_pondicherry_salt_farm.png differ diff --git a/examples/layout/gallery/assets/places/india_tanjore_bronze_works.png b/examples/layout/gallery/assets/places/india_tanjore_bronze_works.png new file mode 100644 index 00000000000..d54c4c32cd5 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_tanjore_bronze_works.png differ diff --git a/examples/layout/gallery/assets/places/india_tanjore_market_merchant.png b/examples/layout/gallery/assets/places/india_tanjore_market_merchant.png new file mode 100644 index 00000000000..d6429685725 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_tanjore_market_merchant.png differ diff --git a/examples/layout/gallery/assets/places/india_tanjore_market_technology.png b/examples/layout/gallery/assets/places/india_tanjore_market_technology.png new file mode 100644 index 00000000000..9b4e838ee17 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_tanjore_market_technology.png differ diff --git a/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple.png b/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple.png new file mode 100644 index 00000000000..be14b4f87fa Binary files /dev/null and b/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple.png differ diff --git a/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple_carvings.png b/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple_carvings.png new file mode 100644 index 00000000000..2ff38388fe2 Binary files /dev/null and b/examples/layout/gallery/assets/places/india_tanjore_thanjavur_temple_carvings.png differ diff --git a/examples/layout/gallery/assets/places/india_thanjavur_market.png b/examples/layout/gallery/assets/places/india_thanjavur_market.png new file mode 100644 index 00000000000..562a55d419d Binary files /dev/null and b/examples/layout/gallery/assets/places/india_thanjavur_market.png differ diff --git a/examples/layout/gallery/lib/bottom_navigation_demo.dart b/examples/layout/gallery/lib/bottom_navigation_demo.dart new file mode 100644 index 00000000000..15c3146cb23 --- /dev/null +++ b/examples/layout/gallery/lib/bottom_navigation_demo.dart @@ -0,0 +1,177 @@ +// Copyright 2019 The Flutter team. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:animations/animations.dart'; +import 'package:flutter/material.dart'; + +class BottomNavigationDemo extends StatefulWidget { + const BottomNavigationDemo({ + super.key, + required this.restorationId, + required this.type, + }); + + final String restorationId; + final BottomNavigationDemoType type; + + @override + State createState() => _BottomNavigationDemoState(); +} + +class _BottomNavigationDemoState extends State + with RestorationMixin { + final RestorableInt _currentIndex = RestorableInt(0); + + @override + String get restorationId => widget.restorationId; + + @override + void restoreState(RestorationBucket? oldBucket, bool initialRestore) { + registerForRestoration(_currentIndex, 'bottom_navigation_tab_index'); + } + + @override + void dispose() { + _currentIndex.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + + var bottomNavigationBarItems = [ + const BottomNavigationBarItem( + icon: Icon(Icons.add_comment), + label: 'Comments', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.calendar_today), + label: 'Calendar', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.account_circle), + label: 'Account', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.alarm_on), + label: 'Alarm', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.camera_enhance), + label: 'Camera', + ), + ]; + + if (widget.type == BottomNavigationDemoType.withLabels) { + bottomNavigationBarItems = bottomNavigationBarItems.sublist( + 0, bottomNavigationBarItems.length - 2); + _currentIndex.value = _currentIndex.value + .clamp(0, bottomNavigationBarItems.length - 1) + .toInt(); + } + + return MaterialApp( + home: Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: Text( + switch (widget.type) { + BottomNavigationDemoType.withLabels => 'Persistent labels', + BottomNavigationDemoType.withoutLabels => 'Selected label', + }, + ), + ), + body: Center( + child: PageTransitionSwitcher( + transitionBuilder: (child, animation, secondaryAnimation) { + return FadeThroughTransition( + animation: animation, + secondaryAnimation: secondaryAnimation, + child: child, + ); + }, + child: _NavigationDestinationView( + // Adding [UniqueKey] to make sure the widget rebuilds when transitioning. + key: UniqueKey(), + item: bottomNavigationBarItems[_currentIndex.value], + ), + ), + ), + bottomNavigationBar: BottomNavigationBar( + showUnselectedLabels: + widget.type == BottomNavigationDemoType.withLabels, + items: bottomNavigationBarItems, + currentIndex: _currentIndex.value, + type: BottomNavigationBarType.fixed, + selectedFontSize: textTheme.bodySmall!.fontSize!, + unselectedFontSize: textTheme.bodySmall!.fontSize!, + onTap: (index) { + setState(() { + _currentIndex.value = index; + }); + }, + selectedItemColor: colorScheme.onPrimary, + unselectedItemColor: colorScheme.onPrimary.withOpacity(0.38), + backgroundColor: colorScheme.primary, + ), + ), + ); + } +} + +class _NavigationDestinationView extends StatelessWidget { + const _NavigationDestinationView({ + super.key, + required this.item, + }); + + final BottomNavigationBarItem item; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + ExcludeSemantics( + child: Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + 'assets/demos/bottom_navigation_background.png', + ), + ), + ), + ), + ), + Center( + child: IconTheme( + data: const IconThemeData( + color: Colors.white, + size: 80, + ), + child: Semantics( + label: 'Placeholder for ${item.label} tab', + child: item.icon, + ), + ), + ), + ], + ); + } +} + +enum BottomNavigationDemoType { + withLabels, + withoutLabels, +} + +void main() { + runApp(const BottomNavigationDemo( + type: BottomNavigationDemoType.withLabels, + restorationId: 'bottom_navigation_labels_demo', + )); +} diff --git a/examples/layout/gallery/lib/cards_demo.dart b/examples/layout/gallery/lib/cards_demo.dart new file mode 100644 index 00000000000..848b9446102 --- /dev/null +++ b/examples/layout/gallery/lib/cards_demo.dart @@ -0,0 +1,426 @@ +// Copyright 2020 The Flutter team. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +enum CardType { + standard, + tappable, + selectable, +} + +class TravelDestination { + const TravelDestination({ + required this.assetName, + required this.title, + required this.description, + required this.city, + required this.location, + this.cardType = CardType.standard, + }); + + final String assetName; + final String title; + final String description; + final String city; + final String location; + final CardType cardType; +} + +const List _destinations = [ + TravelDestination( + assetName: 'places/india_thanjavur_market.png', + title: 'Top 10 Cities to Visit in Tamil Nadu', + description: 'Number 10', + city: 'Thanjavur', + location: 'Thanjavur, Tamil Nadu', + ), + TravelDestination( + assetName: 'places/india_chettinad_silk_maker.png', + title: 'Artisans of Southern India', + description: 'Silk Spinners', + city: 'Chettinad', + location: 'Sivaganga, Tamil Nadu', + cardType: CardType.tappable, + ), + TravelDestination( + assetName: 'places/india_tanjore_thanjavur_temple.png', + title: 'Brihadisvara Temple', + description: 'Temples', + city: 'Thanjavur', + location: 'Thanjavur, Tamil Nadu', + cardType: CardType.selectable, + ), +]; + +class TravelDestinationItem extends StatelessWidget { + const TravelDestinationItem({ + super.key, + required this.destination, + this.shape, + }); + + // Height that allows for all the Card's contents + // to fit comfortably within the card. + static const double height = 360; + final TravelDestination destination; + final ShapeBorder? shape; + + @override + Widget build(BuildContext context) { + return SafeArea( + top: false, + bottom: false, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + const SectionTitle(title: 'Normal'), + SizedBox( + height: height, + child: Card( + // Ensures that the Card's children are clipped correctly. + clipBehavior: Clip.antiAlias, + shape: shape, + child: Semantics( + label: destination.title, + child: TravelDestinationContent(destination: destination), + ), + ), + ), + ], + ), + ), + ); + } +} + +class TappableTravelDestinationItem extends StatelessWidget { + const TappableTravelDestinationItem({ + super.key, + required this.destination, + this.shape, + }); + + // Height that allows for all the Card's contents + // to fit comfortably within the card. + static const double height = 298; + final TravelDestination destination; + final ShapeBorder? shape; + + @override + Widget build(BuildContext context) { + return SafeArea( + top: false, + bottom: false, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + const SectionTitle(title: 'Tappable'), + SizedBox( + height: height, + child: Card( + // Ensures that the Card's children (including the ink splash) + // are clipped correctly. + clipBehavior: Clip.antiAlias, + shape: shape, + child: InkWell( + onTap: () {}, + splashColor: + Theme.of(context).colorScheme.onSurface.withOpacity(0.12), + highlightColor: Colors.transparent, + child: Semantics( + label: destination.title, + child: TravelDestinationContent(destination: destination), + ), + ), + ), + ), + ], + ), + ), + ); + } +} + +class SelectableTravelDestinationItem extends StatelessWidget { + const SelectableTravelDestinationItem({ + super.key, + required this.destination, + required this.isSelected, + required this.onSelected, + this.shape, + }); + + final TravelDestination destination; + final ShapeBorder? shape; + final bool isSelected; + final VoidCallback onSelected; + + // Height that allows for all the Card's contents + // to fit comfortably within the card. + static const double height = 298; + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final String selectedStatus = isSelected ? 'Selected' : 'Not selected'; + + return SafeArea( + top: false, + bottom: false, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + const SectionTitle(title: 'Selectable (long press)'), + SizedBox( + height: height, + child: Card( + // Ensures that the Card's children (including the ink splash) + // are clipped correctly. + clipBehavior: Clip.antiAlias, + shape: shape, + child: InkWell( + onLongPress: () { + onSelected(); + }, + splashColor: colorScheme.onSurface.withOpacity(0.12), + highlightColor: Colors.transparent, + child: Stack( + children: [ + Container( + color: isSelected + ? colorScheme.primary.withOpacity(0.08) + : Colors.transparent, + ), + Semantics( + label: '${destination.title}, $selectedStatus', + onLongPressHint: isSelected ? 'Deselect' : 'Select', + child: + TravelDestinationContent(destination: destination), + ), + Align( + alignment: Alignment.topRight, + child: Padding( + padding: const EdgeInsets.all(8), + child: Icon( + Icons.check_circle, + color: isSelected + ? colorScheme.primary + : Colors.transparent, + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } +} + +class SectionTitle extends StatelessWidget { + const SectionTitle({ + super.key, + required this.title, + }); + + final String title; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(4, 4, 4, 12), + child: Align( + alignment: Alignment.centerLeft, + child: Text(title, style: Theme.of(context).textTheme.titleMedium), + ), + ); + } +} + +class TravelDestinationContent extends StatelessWidget { + const TravelDestinationContent({super.key, required this.destination}); + + final TravelDestination destination; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final titleStyle = theme.textTheme.headlineSmall!.copyWith( + color: Colors.white, + ); + final descriptionStyle = theme.textTheme.titleMedium!; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 184, + child: Stack( + children: [ + Positioned.fill( + // In order to have the ink splash appear above the image, you + // must use Ink.image. This allows the image to be painted as + // part of the Material and display ink effects above it. + // Using a standard Image will obscure the ink splash. + child: Ink.image( + image: AssetImage( + destination.assetName, + ), + fit: BoxFit.cover, + child: Container(), + ), + ), + Positioned( + bottom: 16, + left: 16, + right: 16, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Semantics( + container: true, + header: true, + child: Text( + destination.title, + style: titleStyle, + ), + ), + ), + ), + ], + ), + ), + // Description and share/explore buttons. + Semantics( + container: true, + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 0), + child: DefaultTextStyle( + softWrap: false, + overflow: TextOverflow.ellipsis, + style: descriptionStyle, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // The three line description on each card demo. + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text( + destination.description, + style: descriptionStyle.copyWith(color: Colors.black54), + ), + ), + Text(destination.city), + Text(destination.location), + ], + ), + ), + ), + ), + if (destination.cardType == CardType.standard) + // share, explore buttons + Padding( + padding: const EdgeInsets.all(8), + child: OverflowBar( + alignment: MainAxisAlignment.start, + spacing: 8, + children: [ + TextButton( + onPressed: () {}, + child: Text( + 'Share', + semanticsLabel: 'Share ${destination.title}', + ), + ), + TextButton( + onPressed: () {}, + child: Text( + 'Explore', + semanticsLabel: 'Explore ${destination.title}', + ), + ), + ], + ), + ), + ], + ); + } +} + +class CardsDemo extends StatefulWidget { + const CardsDemo({super.key}); + + @override + State createState() => _CardsDemoState(); +} + +class _CardsDemoState extends State with RestorationMixin { + final RestorableBool _isSelected = RestorableBool(false); + + @override + String get restorationId => 'cards_demo'; + + @override + void restoreState(RestorationBucket? oldBucket, bool initialRestore) { + registerForRestoration(_isSelected, 'is_selected'); + } + + @override + void dispose() { + _isSelected.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + backgroundColor: Colors.green, + appBar: AppBar( + automaticallyImplyLeading: false, + title: const Text('Cards'), + ), + body: Scrollbar( + child: ListView( + restorationId: 'cards_demo_list_view', + padding: const EdgeInsets.only(top: 8, left: 8, right: 8), + children: [ + for (final destination in _destinations) + Container( + margin: const EdgeInsets.only(bottom: 8), + child: switch (destination.cardType) { + CardType.standard => + TravelDestinationItem(destination: destination), + CardType.tappable => + TappableTravelDestinationItem(destination: destination), + CardType.selectable => SelectableTravelDestinationItem( + destination: destination, + isSelected: _isSelected.value, + onSelected: () { + setState(() { + _isSelected.value = !_isSelected.value; + }); + }, + ), + }, + ), + ], + ), + ), + ), + ); + } +} + +void main() { + runApp(const CardsDemo()); +} diff --git a/examples/layout/gallery/lib/colors_demo.dart b/examples/layout/gallery/lib/colors_demo.dart new file mode 100644 index 00000000000..a10cce7626a --- /dev/null +++ b/examples/layout/gallery/lib/colors_demo.dart @@ -0,0 +1,257 @@ +// Copyright 2019 The Flutter team. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +const double _colorItemHeight = 48; + +class _Palette { + const _Palette({ + required this.name, + required this.primary, + this.accent, + this.threshold = 900, + }); + + final String name; + final MaterialColor primary; + final MaterialAccentColor? accent; + + // Titles for indices > threshold are white, otherwise black. + final int threshold; +} + +const List<_Palette> _allPalettes = [ + _Palette( + name: 'Red', + primary: Colors.red, + accent: Colors.redAccent, + threshold: 300, + ), + _Palette( + name: 'Pink', + primary: Colors.pink, + accent: Colors.pinkAccent, + threshold: 200, + ), + _Palette( + name: 'Purple', + primary: Colors.purple, + accent: Colors.purpleAccent, + threshold: 200, + ), + _Palette( + name: 'Deep purple', + primary: Colors.deepPurple, + accent: Colors.deepPurpleAccent, + threshold: 200, + ), + _Palette( + name: 'Indigo', + primary: Colors.indigo, + accent: Colors.indigoAccent, + threshold: 200, + ), + _Palette( + name: 'Blue', + primary: Colors.blue, + accent: Colors.blueAccent, + threshold: 400, + ), + _Palette( + name: 'Light blue', + primary: Colors.lightBlue, + accent: Colors.lightBlueAccent, + threshold: 500, + ), + _Palette( + name: 'Cyan', + primary: Colors.cyan, + accent: Colors.cyanAccent, + threshold: 600, + ), + _Palette( + name: 'Teal', + primary: Colors.teal, + accent: Colors.tealAccent, + threshold: 400, + ), + _Palette( + name: 'Green', + primary: Colors.green, + accent: Colors.greenAccent, + threshold: 500, + ), + _Palette( + name: 'Light green', + primary: Colors.lightGreen, + accent: Colors.lightGreenAccent, + threshold: 600, + ), + _Palette( + name: 'Lime', + primary: Colors.lime, + accent: Colors.limeAccent, + threshold: 800, + ), + _Palette( + name: 'Yellow', + primary: Colors.yellow, + accent: Colors.yellowAccent, + ), + _Palette( + name: 'Amber', + primary: Colors.amber, + accent: Colors.amberAccent, + ), + _Palette( + name: 'Orange', + primary: Colors.orange, + accent: Colors.orangeAccent, + threshold: 700, + ), + _Palette( + name: 'Deep orange', + primary: Colors.deepOrange, + accent: Colors.deepOrangeAccent, + threshold: 400, + ), + _Palette( + name: 'Brown', + primary: Colors.brown, + threshold: 200, + ), + _Palette( + name: 'Grey', + primary: Colors.grey, + threshold: 500, + ), + _Palette( + name: 'Blue grey', + primary: Colors.blueGrey, + threshold: 500, + ), +]; + +class _ColorItem extends StatelessWidget { + const _ColorItem({ + required this.index, + required this.color, + this.prefix = '', + }); + + final int index; + final Color color; + final String prefix; + + String get _colorString => + "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}"; + + @override + Widget build(BuildContext context) { + return Semantics( + container: true, + child: Container( + height: _colorItemHeight, + padding: const EdgeInsets.symmetric(horizontal: 16), + color: color, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text('$prefix$index'), + Flexible(child: Text(_colorString)), + ], + ), + ), + ); + } +} + +class _PaletteTabView extends StatelessWidget { + const _PaletteTabView({required this.colors}); + + final _Palette colors; + static const primaryKeys = [ + 50, + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900 + ]; + static const accentKeys = [100, 200, 400, 700]; + + @override + Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; + final whiteTextStyle = textTheme.bodyMedium!.copyWith( + color: Colors.white, + ); + final blackTextStyle = textTheme.bodyMedium!.copyWith( + color: Colors.black, + ); + return Scrollbar( + child: ListView( + itemExtent: _colorItemHeight, + children: [ + for (final key in primaryKeys) + DefaultTextStyle( + style: key > colors.threshold ? whiteTextStyle : blackTextStyle, + child: _ColorItem(index: key, color: colors.primary[key]!), + ), + if (colors.accent != null) + for (final key in accentKeys) + DefaultTextStyle( + style: key > colors.threshold ? whiteTextStyle : blackTextStyle, + child: _ColorItem( + index: key, + color: colors.accent![key]!, + prefix: 'A', + ), + ), + ], + ), + ); + } +} + +class ColorsDemo extends StatelessWidget { + const ColorsDemo({super.key}); + + @override + Widget build(BuildContext context) { + const palettes = _allPalettes; + return MaterialApp( + home: DefaultTabController( + length: palettes.length, + child: Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: const Text('Colors'), + bottom: TabBar( + isScrollable: true, + tabs: [ + for (final palette in palettes) Tab(text: palette.name), + ], + ), + ), + body: TabBarView( + children: [ + for (final palette in palettes) _PaletteTabView(colors: palette), + ], + ), + ), + ), + ); + } +} + +void main() { + runApp(const ColorsDemo()); +} diff --git a/examples/layout/gallery/lib/grid_list_demo.dart b/examples/layout/gallery/lib/grid_list_demo.dart new file mode 100644 index 00000000000..93dec8a96a5 --- /dev/null +++ b/examples/layout/gallery/lib/grid_list_demo.dart @@ -0,0 +1,196 @@ +// Copyright 2019 The Flutter team. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +class GridListDemo extends StatelessWidget { + const GridListDemo({super.key, required this.type}); + + final GridListDemoType type; + + static const List<_Photo> _photos = [ + _Photo( + assetName: 'places/india_chennai_flower_market.png', + title: 'Chennai', + subtitle: 'Flower Market', + ), + _Photo( + assetName: 'places/india_tanjore_bronze_works.png', + title: 'Tanjore', + subtitle: 'Bronze Works', + ), + _Photo( + assetName: 'places/india_tanjore_market_merchant.png', + title: 'Tanjore', + subtitle: 'Market', + ), + _Photo( + assetName: 'places/india_tanjore_thanjavur_temple.png', + title: 'Tanjore', + subtitle: 'Thanjavur Temple', + ), + _Photo( + assetName: 'places/india_tanjore_thanjavur_temple_carvings.png', + title: 'Tanjore', + subtitle: 'Thanjavur Temple', + ), + _Photo( + assetName: 'places/india_pondicherry_salt_farm.png', + title: 'Pondicherry', + subtitle: 'Salt Farm', + ), + _Photo( + assetName: 'places/india_chennai_highway.png', + title: 'Chennai', + subtitle: 'Scooters', + ), + _Photo( + assetName: 'places/india_chettinad_silk_maker.png', + title: 'Chettinad', + subtitle: 'Silk Maker', + ), + _Photo( + assetName: 'places/india_chettinad_produce.png', + title: 'Chettinad', + subtitle: 'Lunch Prep', + ), + _Photo( + assetName: 'places/india_tanjore_market_technology.png', + title: 'Tanjore', + subtitle: 'Market', + ), + _Photo( + assetName: 'places/india_pondicherry_beach.png', + title: 'Pondicherry', + subtitle: 'Beach', + ), + _Photo( + assetName: 'places/india_pondicherry_fisherman.png', + title: 'Pondicherry', + subtitle: 'Fisherman', + ), + ]; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: const Text('Grid view'), + ), + body: GridView.count( + restorationId: 'grid_view_demo_grid_offset', + crossAxisCount: 2, + mainAxisSpacing: 8, + crossAxisSpacing: 8, + padding: const EdgeInsets.all(8), + childAspectRatio: 1, + children: _photos.map((photo) { + return _GridDemoPhotoItem( + photo: photo, + tileStyle: type, + ); + }).toList(), + ), + ), + ); + } +} + +class _Photo { + const _Photo({ + required this.assetName, + required this.title, + required this.subtitle, + }); + + final String assetName; + final String title; + final String subtitle; +} + +/// Allow the text size to shrink to fit in the space. +class _GridTitleText extends StatelessWidget { + const _GridTitleText(this.text); + + final String text; + + @override + Widget build(BuildContext context) { + return FittedBox( + fit: BoxFit.scaleDown, + alignment: AlignmentDirectional.centerStart, + child: Text(text), + ); + } +} + +class _GridDemoPhotoItem extends StatelessWidget { + const _GridDemoPhotoItem({ + required this.photo, + required this.tileStyle, + }); + + final _Photo photo; + final GridListDemoType tileStyle; + + @override + Widget build(BuildContext context) { + final Widget image = Semantics( + label: '${photo.title} ${photo.subtitle}', + child: Material( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)), + clipBehavior: Clip.antiAlias, + child: Image.asset( + photo.assetName, + fit: BoxFit.cover, + ), + ), + ); + + return switch (tileStyle) { + GridListDemoType.imageOnly => image, + GridListDemoType.header => GridTile( + header: Material( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(4)), + ), + clipBehavior: Clip.antiAlias, + child: GridTileBar( + title: _GridTitleText(photo.title), + backgroundColor: Colors.black45, + ), + ), + child: image, + ), + GridListDemoType.footer => GridTile( + footer: Material( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(bottom: Radius.circular(4)), + ), + clipBehavior: Clip.antiAlias, + child: GridTileBar( + backgroundColor: Colors.black45, + title: _GridTitleText(photo.title), + subtitle: _GridTitleText(photo.subtitle), + ), + ), + child: image, + ) + }; + } +} + +enum GridListDemoType { + imageOnly, + header, + footer, +} + +void main() { + runApp(const GridListDemo(type: GridListDemoType.footer)); +} diff --git a/examples/layout/gallery/lib/list_demo.dart b/examples/layout/gallery/lib/list_demo.dart new file mode 100644 index 00000000000..9ba47a112fe --- /dev/null +++ b/examples/layout/gallery/lib/list_demo.dart @@ -0,0 +1,53 @@ +// Copyright 2019 The Flutter team. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +class ListDemo extends StatelessWidget { + const ListDemo({super.key, required this.type}); + + final ListDemoType type; + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), + ), + home: Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: const Text('List demo'), + ), + body: Scrollbar( + child: ListView( + restorationId: 'list_demo_list_view', + padding: const EdgeInsets.symmetric(vertical: 8), + children: [ + for (var index = 1; index < 21; index++) + ListTile( + leading: ExcludeSemantics( + child: CircleAvatar(child: Text('$index')), + ), + title: Text('Item $index'), + subtitle: type == ListDemoType.twoLine + ? const Text('Secondary text') + : null, + ), + ], + ), + ), + ), + ); + } +} + +enum ListDemoType { + oneLine, + twoLine, +} + +void main() { + runApp(const ListDemo(type: ListDemoType.twoLine)); +} diff --git a/examples/layout/gallery/pubspec.yaml b/examples/layout/gallery/pubspec.yaml new file mode 100644 index 00000000000..7ea840e5f06 --- /dev/null +++ b/examples/layout/gallery/pubspec.yaml @@ -0,0 +1,35 @@ +name: gallery +description: >- + Legacy examples referenced in "Layouts in Flutter": + https://docs.flutter.dev/ui/layout. +version: 1.0.0 + +environment: + sdk: ^3.2.0 + +dependencies: + animations: ^2.0.11 + flutter: + sdk: flutter + +dev_dependencies: + example_utils: + path: ../../example_utils + +flutter: + uses-material-design: true + assets: + - assets/demos/bottom_navigation_background.png + - assets/places/india_chennai_flower_market.png + - assets/places/india_thanjavur_market.png + - assets/places/india_tanjore_bronze_works.png + - assets/places/india_tanjore_market_merchant.png + - assets/places/india_tanjore_thanjavur_temple.png + - assets/places/india_pondicherry_salt_farm.png + - assets/places/india_chennai_highway.png + - assets/places/india_chettinad_silk_maker.png + - assets/places/india_tanjore_thanjavur_temple_carvings.png + - assets/places/india_chettinad_produce.png + - assets/places/india_tanjore_market_technology.png + - assets/places/india_pondicherry_beach.png + - assets/places/india_pondicherry_fisherman.png diff --git a/src/_data/sidenav.yml b/src/_data/sidenav.yml index 52aca989a0d..487a739bb4b 100644 --- a/src/_data/sidenav.yml +++ b/src/_data/sidenav.yml @@ -48,16 +48,14 @@ - title: Compatibility policy permalink: /release/compatibility-policy -- title: Samples & codelabs +- title: Codelabs & samples children: - - title: Flutter Gallery - permalink: https://gallery.flutter.dev - - title: Samples and demos - permalink: https://flutter.github.io/samples/ - - title: Cookbook - permalink: /cookbook - title: Codelabs permalink: /codelabs + - title: Cookbook + permalink: /cookbook + - title: Samples and demos + permalink: https://flutter.github.io/samples/ - title: App solutions children: diff --git a/src/assets/images/docs/ui/layout/card-flutter-gallery.png b/src/assets/images/docs/ui/layout/card-flutter-gallery.png index a5ddd1514fc..91d898c3a89 100644 Binary files a/src/assets/images/docs/ui/layout/card-flutter-gallery.png and b/src/assets/images/docs/ui/layout/card-flutter-gallery.png differ diff --git a/src/assets/images/docs/ui/layout/gridview-count-flutter-gallery.png b/src/assets/images/docs/ui/layout/gridview-count-flutter-gallery.png index 34a631ba337..2440afd9563 100644 Binary files a/src/assets/images/docs/ui/layout/gridview-count-flutter-gallery.png and b/src/assets/images/docs/ui/layout/gridview-count-flutter-gallery.png differ diff --git a/src/assets/images/docs/ui/layout/listtile-flutter-gallery.png b/src/assets/images/docs/ui/layout/listtile-flutter-gallery.png index 2bd4c1f7d67..dfcd9ea42c3 100644 Binary files a/src/assets/images/docs/ui/layout/listtile-flutter-gallery.png and b/src/assets/images/docs/ui/layout/listtile-flutter-gallery.png differ diff --git a/src/assets/images/docs/ui/layout/listview-color-gallery.png b/src/assets/images/docs/ui/layout/listview-color-gallery.png new file mode 100644 index 00000000000..f1c753ec18e Binary files /dev/null and b/src/assets/images/docs/ui/layout/listview-color-gallery.png differ diff --git a/src/assets/images/docs/ui/layout/listview-flutter-gallery.png b/src/assets/images/docs/ui/layout/listview-flutter-gallery.png deleted file mode 100644 index 3fdbec5df06..00000000000 Binary files a/src/assets/images/docs/ui/layout/listview-flutter-gallery.png and /dev/null differ diff --git a/src/assets/images/docs/ui/layout/stack-flutter-gallery.png b/src/assets/images/docs/ui/layout/stack-flutter-gallery.png index b1e9407ae41..79fcdc25585 100644 Binary files a/src/assets/images/docs/ui/layout/stack-flutter-gallery.png and b/src/assets/images/docs/ui/layout/stack-flutter-gallery.png differ diff --git a/src/deployment/cd.md b/src/deployment/cd.md index e837edcfedd..03e5adf66ae 100644 --- a/src/deployment/cd.md +++ b/src/deployment/cd.md @@ -24,7 +24,6 @@ options available to help automate the delivery of your application. You can use fastlane with the following tooling: * [GitHub Actions][] - * Example: Flutter Gallery's [Github Actions workflows][] * Example: [Github Action in Flutter Project][] * [Cirrus][] * [Travis][] @@ -317,10 +316,8 @@ information. [fastlane Android beta deployment guide]: https://docs.fastlane.tools/getting-started/android/beta-deployment/ [fastlane CI documentation]: https://docs.fastlane.tools/best-practices/continuous-integration [fastlane iOS beta deployment guide]: https://docs.fastlane.tools/getting-started/ios/beta-deployment/ -[Flutter Gallery Project]: {{site.repo.gallery}} [Github Action in Flutter Project]: {{site.github}}/nabilnalakath/flutter-githubaction [GitHub Actions]: {{site.github}}/features/actions -[Github Actions workflows]: {{site.repo.gallery}}/tree/main/.github/workflows [GitLab]: https://docs.gitlab.com/ee/ci/README.html#doc-nav [CircleCI]: https://circleci.com [Building and deploying Flutter apps with Fastlane]: https://circleci.com/blog/deploy-flutter-android diff --git a/src/deployment/windows.md b/src/deployment/windows.md index 50353b7e31e..3c88e1192da 100644 --- a/src/deployment/windows.md +++ b/src/deployment/windows.md @@ -140,21 +140,22 @@ and in a GitHub Action packages the application into an MSIX and uploads it to a new submission on the dev center. -An example Action YAML file for continuous deployment can be found -[in the Flutter Gallery](https://github.com/flutter/gallery/blob/main/.github/workflows/release_deploy_windows.yml). -The steps necessary for MSIX publishing are excerpted below: +The steps necessary for MSIX publishing resemble the following ``` - - uses: microsoft/setup-msstore-cli@v1 +- uses: microsoft/setup-msstore-cli@v1 - - name: Configure the Microsoft Store CLI - run: msstore reconfigure --tenantId ${{ secrets.AZURE_AD_TENANT_ID }} --clientId ${{ secrets.AZURE_AD_ClIENT_ID }} --clientSecret ${{ secrets.AZURE_AD_CLIENT_SECRET }} --sellerId ${{ secrets.SELLER_ID }} +- name: Configure the Microsoft Store CLI + run: msstore reconfigure --tenantId ${{ secrets.AZURE_AD_TENANT_ID }} --clientId ${{ secrets.AZURE_AD_ClIENT_ID }} --clientSecret ${{ secrets.AZURE_AD_CLIENT_SECRET }} --sellerId ${{ secrets.SELLER_ID }} - - name: Create MSIX - run: msstore package . +- name: Install Dart dependencies + run: flutter pub get - - name: Publish MSIX to the Microsoft Store - run: msstore publish -v +- name: Create MSIX package + run: msstore package . + +- name: Publish MSIX to the Microsoft Store + run: msstore publish -v ``` ## Updating the app's version number diff --git a/src/perf/best-practices.md b/src/perf/best-practices.md index 253508ca364..f2ad42a370e 100644 --- a/src/perf/best-practices.md +++ b/src/perf/best-practices.md @@ -26,7 +26,7 @@ write the most performant Flutter app possible. * [Building performant Flutter widgets][web-perf-3] {{site.alert.end}} -[Flutter Gallery]: {{site.gallery}} +[Flutter Gallery]: {{site.gallery-archive}} [web-perf-1]: {{site.flutter-medium}}/optimizing-performance-in-flutter-web-apps-with-tree-shaking-and-deferred-loading-535fbe3cd674 [web-perf-2]: {{site.flutter-medium}}/improving-perceived-performance-with-image-placeholders-precaching-and-disabled-navigation-6b3601087a2b [web-perf-3]: {{site.flutter-medium}}/building-performant-flutter-widgets-3b2558aa08fa diff --git a/src/perf/deferred-components.md b/src/perf/deferred-components.md index 2a51f684d92..2584e386731 100644 --- a/src/perf/deferred-components.md +++ b/src/perf/deferred-components.md @@ -279,7 +279,7 @@ The `loadLibrary()` function can also be called early to trigger a pre-load to help mask the loading time. You can find another example of deferred import loading in -[Flutter Gallery's lib/deferred_widget.dart][]. +[Flutter Gallery's `lib/deferred_widget.dart`][]. @@ -595,7 +595,7 @@ Play store's delivery feature. [Deferred Components]: {{site.repo.flutter}}/wiki/Deferred-Components [`DeferredComponent`]: {{site.api}}/flutter/services/DeferredComponent-class.html [dynamic feature modules]: {{site.android-dev}}/guide/playcore/feature-delivery -[Flutter Gallery's lib/deferred_widget.dart]: {{site.repo.gallery}}/blob/main/lib/deferred_widget.dart +[Flutter Gallery's `lib/deferred_widget.dart`]: {{site.repo.gallery-archive}}/blob/main/lib/deferred_widget.dart [Flutter wiki]: {{site.repo.flutter}}/wiki [github.com/google/bundletool/releases]: {{site.github}}/google/bundletool/releases [lazily loading a library]: {{site.dart-site}}/language/libraries#lazily-loading-a-library diff --git a/src/platform-integration/desktop.md b/src/platform-integration/desktop.md index 068c38fd277..91f80c01311 100644 --- a/src/platform-integration/desktop.md +++ b/src/platform-integration/desktop.md @@ -309,14 +309,13 @@ You can run the following samples as desktop apps, as well as download and inspect the source code to learn more about Flutter desktop support. -Flutter Gallery [running web app][], [repo][flutter-gallery-repo] -: A samples project hosted on GitHub to help developers - evaluate and use Flutter. The Gallery consists of a - collection of Material design widgets, behaviors, - and vignettes implemented with Flutter. - You can clone the project and run Gallery as a desktop app - by following the instructions provided in the [README][]. - +Wonderous app [running app][wonderous-app], [repo][wonderous-repo] +: A showcase app that uses Flutter to create a highly expressive user interface. + Wonderous focuses on delivering an accessible and high-quality user experience + while including engaging interactions and novel animations. + To run Wonderous as a desktop app, clone the project and + follow the instructions provided in the [README][wonderous-readme]. + Flokk [announcement blogpost][gskinner-flokk-blogpost], [repo][gskinner-flokk-repo] : A Google contacts manager that integrates with GitHub and Twitter. It syncs with your Google account, imports your contacts, @@ -326,10 +325,10 @@ Flokk [announcement blogpost][gskinner-flokk-blogpost], [repo][gskinner-flokk-re : A sample application built as a desktop application that uses desktop-supported plugins. +[wonderous-app]: {{site.wonderous}}/web +[wonderous-repo]: {{site.repo.wonderous}} +[wonderous-readme]: {{site.repo.wonderous}}#wonderous [Photo Search app]: {{site.repo.samples}}/tree/main/desktop_photo_search -[running web app]: {{site.gallery}} -[flutter-gallery-repo]: {{site.repo.gallery}} -[README]: {{site.repo.gallery}}#readme [gskinner-flokk-repo]: {{site.github}}/gskinnerTeam/flokk [gskinner-flokk-blogpost]: https://blog.gskinner.com/archives/2020/09/flokk-how-we-built-a-desktop-app-using-flutter.html [Write a Flutter desktop application]: {{site.codelabs}}/codelabs/flutter-github-client diff --git a/src/platform-integration/web/index.md b/src/platform-integration/web/index.md index ddffa13f4fa..85e53c9c442 100644 --- a/src/platform-integration/web/index.md +++ b/src/platform-integration/web/index.md @@ -75,7 +75,7 @@ The following resources can help you get started: [web FAQ][]. * To see code examples, check out the [web samples for Flutter][]. -* To see a Flutter web app demo, check out the [Flutter Gallery][]. +* To see a Flutter web app demo, check out the [Wonderous app][]. * To learn about deploying a web app, see [Preparing an app for web release][]. * [File an issue][] on the main Flutter repo. @@ -88,7 +88,7 @@ The following resources can help you get started: [Creating responsive apps]: {{site.url}}/ui/layout/responsive/adaptive-responsive [Discord]: https://discordapp.com/invite/yeZ6s7k [file an issue]: https://goo.gle/flutter_web_issue -[Flutter Gallery]: {{site.gallery}} +[Wonderous app]: {{site.wonderous}}/web [Preparing an app for web release]: {{site.url}}/deployment/web [Progressive Web Application]: https://web.dev/progressive-web-apps/ [web FAQ]: {{site.url}}/platform-integration/web/faq diff --git a/src/platform-integration/web/initialization.md b/src/platform-integration/web/initialization.md index 3c0811aabbd..ba4b097404f 100644 --- a/src/platform-integration/web/initialization.md +++ b/src/platform-integration/web/initialization.md @@ -231,7 +231,7 @@ use the hooks provided for each stage to update the DOM: For a more practical example using CSS animations, see the [initialization code][gallery-init] for the Flutter Gallery. -[gallery-init]: {{site.repo.gallery}}/blob/master/web/index.html +[gallery-init]: {{site.repo.gallery-archive}}/blob/main/web/index.html ## Upgrading an older project diff --git a/src/release/breaking-changes/windows-dark-mode.md b/src/release/breaking-changes/windows-dark-mode.md index 723f390f100..74d1f77544a 100644 --- a/src/release/breaking-changes/windows-dark-mode.md +++ b/src/release/breaking-changes/windows-dark-mode.md @@ -41,5 +41,5 @@ Flutter SDK [Flutter Gallery][] app. [run loop migration guide]: {{site.url}}/release/breaking-changes/windows-run-loop -[PR 862]: {{site.repo.gallery}}/pull/862/files -[Flutter Gallery]: {{site.gallery}} \ No newline at end of file +[PR 862]: {{site.repo.gallery-archive}}/pull/862/files +[Flutter Gallery]: {{site.gallery-archive}} \ No newline at end of file diff --git a/src/release/breaking-changes/windows-show-window-migration.md b/src/release/breaking-changes/windows-show-window-migration.md index 0f9b989931e..2e476441d66 100644 --- a/src/release/breaking-changes/windows-show-window-migration.md +++ b/src/release/breaking-changes/windows-show-window-migration.md @@ -47,5 +47,5 @@ flutter_controller_->ForceRedraw(); [PR 995][] shows the migration work for the [Flutter Gallery][] app. -[PR 995]: {{site.repo.gallery}}/pull/995/files -[Flutter Gallery]: {{site.gallery}} \ No newline at end of file +[PR 995]: {{site.repo.gallery-archive}}/pull/995/files +[Flutter Gallery]: {{site.gallery-archive}} \ No newline at end of file diff --git a/src/release/breaking-changes/windows-version-information.md b/src/release/breaking-changes/windows-version-information.md index f11939604cc..f3be2d6907d 100644 --- a/src/release/breaking-changes/windows-version-information.md +++ b/src/release/breaking-changes/windows-version-information.md @@ -42,5 +42,5 @@ files [Build and release a Windows app]: {{site.url}}/deployment/windows#updating-the-apps-version-number [run loop migration guide]: {{site.url}}/release/breaking-changes/windows-run-loop -[PR 721]: {{site.repo.gallery}}/pull/721/files -[Flutter Gallery]: {{site.gallery}} \ No newline at end of file +[PR 721]: {{site.repo.gallery-archive}}/pull/721/files +[Flutter Gallery]: {{site.gallery-archive}} \ No newline at end of file diff --git a/src/release/whats-new.md b/src/release/whats-new.md index cdb4036e638..f547d2cccdb 100644 --- a/src/release/whats-new.md +++ b/src/release/whats-new.md @@ -1188,9 +1188,7 @@ Docs added and updated since the last announcement include: Other newness: -* A brand new version of [Flutter Gallery][]. There's a - link to the runnable sample in the side nav under - **Samples & Tutorials**. +* A brand-new version of [Flutter Gallery][]. Happy Fluttering! @@ -1201,7 +1199,7 @@ Happy Fluttering! [Flutter: the first UI platform designed for ambient computing]: {{site.google-blog}}/2019/12/flutter-ui-ambient-computing.html?m=1 [Flutter Favorite program]: {{site.url}}/packages-and-plugins/favorites [Flutter 1.12.13]: {{site.url}}/release/release-notes/release-notes-1.12.13 -[Flutter Gallery]: https://flutter.github.io/samples/#/ +[Flutter Gallery]: {{site.gallery-archive}} [Flutter Layout Explorer]: {{site.url}}/tools/devtools/inspector#flutter-layout-explorer [Flutter Medium publication]: {{site.medium}}/flutter [Migrating your plugin to the new Android APIs]: {{site.url}}/release/breaking-changes/plugin-api-migration diff --git a/src/ui/accessibility-and-internationalization/accessibility.md b/src/ui/accessibility-and-internationalization/accessibility.md index 0f1e43d061b..e54e344787b 100644 --- a/src/ui/accessibility-and-internationalization/accessibility.md +++ b/src/ui/accessibility-and-internationalization/accessibility.md @@ -206,9 +206,8 @@ To learn about using Orca, check out
-Check out the following [video demo][] to see -Victor Tsaran, who leads the Accessibility program for Material Design, -using VoiceOver with the Flutter Gallery web app. +Check out the following [video demo][] to see Victor Tsaran, +using VoiceOver with the now-archived [Flutter Gallery][] web app. Flutter's standard widgets generate an accessibility tree automatically. However, if your app needs something different, @@ -222,6 +221,7 @@ don't affect which voice the screen reader uses. Usually, the screen reader uses the system voice except where you explicitly set it with `TextSpan.locale`. +[Flutter Gallery]: {{site.gallery-archive}} [`TextSpan.locale`]: {{site.api}}/flutter/painting/TextSpan/locale.html ## Sufficient contrast diff --git a/src/ui/animations/index.md b/src/ui/animations/index.md index a85c64ac7ca..112cf0ce188 100644 --- a/src/ui/animations/index.md +++ b/src/ui/animations/index.md @@ -127,12 +127,6 @@ Similarly, dropping a ball attached to a spring falls * [Animate a widget using a physics simulation][]
A recipe in the animations section of the Flutter cookbook. -* [Flutter Gallery][]
- Under **Material Components**, the [`Grid`][] example - demonstrates a fling animation. Select one of the - images from the grid and zoom in. You can pan the - image with flinging or dragging gestures. - * Also see the API documentation for [`AnimationController.animateWith`][] and [`SpringSimulation`][]. @@ -179,11 +173,6 @@ using the `Hero` widget. * The hero's boundary changes shape, from a circle to a square, as its flies from one page to another. -* [Flutter Gallery][]
- You can build the Gallery app yourself, - or download it from the Play Store. The [Shrine][] - demo includes an example of a hero animation. - * Also see the API documentation for the [`Hero`][], [`Navigator`][], and [`PageRoute`][] classes. @@ -246,8 +235,6 @@ Learn more about Flutter animations at the following links: [Creating your own custom implicit animations with TweenAnimationBuilder]: {{yt-watch}}?v=6KiPEqzJIKQ&feature=youtu.be [Creating custom explicit animations with AnimatedBuilder and AnimatedWidget]: {{yt-watch}}?v=fneC7t4R_B0&list=PLjxrf2q8roU2v6UqYlt_KPaXlnjbYySua&index=4 [Flutter API documentation]: {{site.api}} -[Flutter Gallery]: {{site.repo.gallery}} -[`Grid`]: {{site.repo.gallery}}/blob/main/lib/demos/material/grid_list_demo.dart [`Hero`]: {{site.api}}/flutter/widgets/Hero-class.html [Hero animations]: {{site.url}}/ui/animations/hero-animations [How to choose which Flutter Animation Widget is right for you?]: {{yt-watch}}?v=GXIJJkq_H8g @@ -258,7 +245,6 @@ Learn more about Flutter animations at the following links: [`PageRoute`]: {{site.api}}/flutter/widgets/PageRoute-class.html [part 2]: {{site.medium}}/dartlang/zero-to-one-with-flutter-part-two-5aa2f06655cb [Sample app catalog]: https://flutter.github.io/samples -[Shrine]: {{site.repo.gallery}}/tree/main/lib/studies/shrine [`SpringSimulation`]: {{site.api}}/flutter/physics/SpringSimulation-class.html [Staggered Animations]: {{site.url}}/ui/animations/staggered-animations [Write your first Flutter app on the web]: {{site.url}}/get-started/codelab-web diff --git a/src/ui/interactivity/index.md b/src/ui/interactivity/index.md index a2ed73416cd..2eb19f86b97 100644 --- a/src/ui/interactivity/index.md +++ b/src/ui/interactivity/index.md @@ -775,9 +775,8 @@ to your app. [Flutter API documentation][] : Reference documentation for all of the Flutter libraries. -Flutter Gallery [running app][], [repo][] -: Demo app showcasing many Material components and - other Flutter features. +Wonderous app [running app][wonderous-app], [repo][wonderous-repo] +: Flutter showcase app with a custom design and engaging interactions. [Flutter's Layered Design][] (video) : This video includes information about state and @@ -817,8 +816,8 @@ Flutter Gallery [running app][], [repo][] [`pubspec.yaml`]: {{examples}}/layout/lakes/step6/pubspec.yaml [`Radio`]: {{site.api}}/flutter/material/Radio-class.html [`ElevatedButton`]: {{site.api}}/flutter/material/ElevatedButton-class.html -[repo]: {{site.repo.gallery}} -[running app]: {{site.gallery}} +[wonderous-app]: {{site.wonderous}}/web +[wonderous-repo]: {{site.repo.wonderous}} [set up]: {{site.url}}/get-started/install [`SizedBox`]: {{site.api}}/flutter/widgets/SizedBox-class.html [`Slider`]: {{site.api}}/flutter/material/Slider-class.html diff --git a/src/ui/layout/index.md b/src/ui/layout/index.md index b86c28fc902..eafea0837fd 100644 --- a/src/ui/layout/index.md +++ b/src/ui/layout/index.md @@ -8,9 +8,7 @@ diff2html: true {% include docs/yt_shims.liquid %} {% assign api = site.api | append: '/flutter' -%} -{% capture code -%} {{site.repo.this}}/tree/{{site.branch}}/src/_includes/code {%- endcapture -%} {% capture examples -%} {{site.repo.this}}/tree/{{site.branch}}/examples {%- endcapture -%} -{% capture demo -%} {{site.repo.gallery}}/tree/{{site.branch}}/lib/demos {%- endcapture -%} @@ -48,7 +46,7 @@ The second screenshot displays the visual layout, showing a row of {{site.alert.note}} Most of the screenshots in this tutorial are displayed with - `debugPaintSizeEnabled` set to true so you can see the visual layout. + `debugPaintSizeEnabled` set to `true` so you can see the visual layout. For more information, see [Debugging layout issues visually][], a section in [Using the Flutter inspector][]. @@ -206,7 +204,7 @@ You need to set these yourself. You can use the colors that [`CupertinoColors`][] provides to configure your widgets to match iOS design. -* To layout the body of your app, set the `child` property of your scaffold +* To lay out the body of your app, set the `child` property of your scaffold with the desired widget as its value, like `Center` or `Column`. To learn what other UI components you can add, check out the @@ -288,7 +286,7 @@ class MyApp extends StatelessWidget { } ``` -By default a non-Material app doesn't include an `AppBar`, title, +By default, a non-Material app doesn't include an `AppBar`, title, or background color. If you want these features in a non-Material app, you have to build them yourself. This app changes the background color to white and the text to dark grey to mimic a Material app. @@ -860,8 +858,7 @@ Widget _buildImageRow(int imageIndex) => Row( ); ``` -You can find more `Container` examples in the [tutorial][] -and the Flutter Gallery ([running app][], [repo][]). +You can find more `Container` examples in the [tutorial][]. **App source:** [container]({{examples}}/layout/container) @@ -921,8 +918,8 @@ it automatically scrolls. The titles are created by setting the `footer` property for each [`GridTile`][]. - **Dart code:** [grid_list_demo.dart]({{demo}}/material/grid_list_demo.dart) - from the [Flutter Gallery][repo] + **Dart code:** + [`grid_list_demo.dart`]({{examples}}/layout/gallery/lib/grid_list_demo.dart) @@ -975,16 +972,16 @@ its render box. **App source:** [grid_and_list]({{examples}}/layout/grid_and_list)
- ListView containing shades of blue {:.text-center} Uses `ListView` to display the [`Colors`][] from - the [Material Design palette][] + the [Material 2 Design palette][] for a particular color family. - **Dart code:** [colors_demo.dart]({{demo}}/reference/colors_demo.dart) from the - [Flutter Gallery][repo] + **Dart code:** + [`colors_demo.dart`]({{examples}}/layout/gallery/lib/colors_demo.dart)
@@ -1064,8 +1061,8 @@ or partially overlap the base widget. Uses `Stack` to overlay an icon on top of an image. - **Dart code:** [bottom_navigation_demo.dart]({{demo}}/material/bottom_navigation_demo.dart) - from the [Flutter Gallery][repo] + **Dart code:** + [`bottom_navigation_demo.dart`]({{examples}}/layout/gallery/lib/bottom_navigation_demo.dart) @@ -1147,13 +1144,13 @@ Specifying an unsupported value disables the drop shadow entirely.
Card containing an image, text and buttons + alt="Tappable card containing an image and multiple forms of text"> {:.text-center} A `Card` containing an image and text. - **Dart code:** [cards_demo.dart]({{demo}}/material/cards_demo.dart) - from the [Flutter Gallery][repo] + **Dart code:** + [`cards_demo.dart`]({{examples}}/layout/gallery/lib/cards_demo.dart)
@@ -1236,9 +1233,10 @@ and trailing icons. `ListTile` is most commonly used in alt="4 ListTiles, each containing a leading avatar"> {:.text-center} - Uses `ListTile` with leading widgets.
- **Dart code:** [list_demo.dart]({{demo}}/material/list_demo.dart) - from the [Flutter Gallery][repo] + Uses `ListTile` with leading widgets. + + **Dart code:** + [`list_demo.dart`]({{examples}}/layout/gallery/lib/list_demo.dart) @@ -1284,10 +1282,6 @@ The following resources might help when writing layout code. : For those familiar with web programming, this page maps HTML/CSS functionality to Flutter features. -* Flutter Gallery [running app][], [repo][] -: Demo app showcasing many Material Design widgets and other - Flutter features. - * [API reference docs][] : Reference documentation for all of the Flutter libraries. @@ -1325,13 +1319,11 @@ The following resources might help when writing layout code. [`MainAxisAlignment`]: {{api}}/rendering/MainAxisAlignment.html [Material card]: {{site.material}}/components/cards [Material Design]: {{site.material}}/styles -[Material Design palette]: {{site.material2}}/design/color/the-color-system.html#tools-for-picking-colors +[Material 2 Design palette]: {{site.material2}}/design/color/the-color-system.html#tools-for-picking-colors [Material library]: {{api}}/material/material-library.html [pubspec file]: {{examples}}/layout/pavlova/pubspec.yaml [`pubspec.yaml` file]: {{examples}}/layout/row_column/pubspec.yaml -[repo]: {{site.repo.gallery}}/tree/main [`Row`]: {{api}}/widgets/Row-class.html -[running app]: {{site.gallery}} [`Scaffold`]: {{api}}/material/Scaffold-class.html [`SizedBox`]: {{api}}/widgets/SizedBox-class.html [`Stack`]: {{api}}/widgets/Stack-class.html diff --git a/src/ui/layout/responsive/adaptive-responsive.md b/src/ui/layout/responsive/adaptive-responsive.md index 3f149653557..eed75ad4b1e 100644 --- a/src/ui/layout/responsive/adaptive-responsive.md +++ b/src/ui/layout/responsive/adaptive-responsive.md @@ -156,10 +156,10 @@ You can learn more about creating platform adaptive apps in the following resources: * [Platform-specific behaviors and adaptations][], a page on this site. +* [Extreme UI Adaptability in Flutter][], the story of how Google Earth is + using Flutter to take adaptability to the next level. * [Designing truly adaptive user interfaces][] a blog post and video by Aloïs Deniel, presented at the Flutter Vikings 2020 conference. -* The [Flutter gallery app][] ([repo][]) has been written as an - adaptive app. [Adaptive layouts]: {{yt-watch}}?v=n6Awpg1MO6M&t=694s [Adaptive layouts, part 2]: {{yt-watch}}?v=eikOZzfc0l4&t=11s @@ -167,8 +167,7 @@ in the following resources: [Building adaptive apps]: {{site.url}}/ui/layout/responsive/building-adaptive-apps [Designing truly adaptive user interfaces]: https://www.aloisdeniel.com/blog/designing-truly-adaptative-user-interfaces -[Flutter gallery app]: {{site.gallery}} [Folio source code]: {{site.github}}/gskinnerTeam/flutter-folio [gskinner blog]: https://blog.gskinner.com/ [Platform-specific behaviors and adaptations]: {{site.url}}/platform-integration/platform-adaptations -[repo]: {{site.repo.gallery}} +[Extreme UI Adaptability in Flutter]: {{site.flutter-medium}}/extreme-ui-adaptability-in-flutter-how-google-earth-supports-every-use-case-on-earth-6db4661e7a17 diff --git a/src/ui/layout/tutorial.md b/src/ui/layout/tutorial.md index d3fcec0403b..5bcbd046777 100644 --- a/src/ui/layout/tutorial.md +++ b/src/ui/layout/tutorial.md @@ -8,7 +8,6 @@ diff2html: true {% assign api = site.api | append: '/flutter' -%} {% capture examples -%} {{site.repo.this}}/tree/{{site.branch}}/examples {%- endcapture -%} {% assign rawExFile = '' -%} -{% capture demo -%} {{site.repo.flutter}}/tree/{{site.branch}}/examples/flutter_gallery/lib/demo {%- endcapture -%} @@ -126,7 +125,7 @@ to contain each part of your layout. When Flutter needs to re-render part of a UI, it updates the smallest part that changes. This is why Flutter makes "everything a widget". -If the only the text changes in a `Text` widget, Flutter redraws only that text. +If only the text changes in a `Text` widget, Flutter redraws only that text. Flutter changes the least amount of the UI possible in response to user input. For this tutorial, write each element you have identified as its own widget.