1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-10 23:08:59 +00:00

Flutter 3.29 beta (#2571)

This commit is contained in:
Eric Windmill
2025-02-12 18:08:01 -05:00
committed by GitHub
parent d62c784789
commit 719fd72c38
685 changed files with 76244 additions and 53721 deletions

View File

@@ -69,10 +69,7 @@ class _PlatformAdaptingHomePageState extends State<PlatformAdaptingHomePage> {
// all 4 possible tabs. This drawer is injected into the songs tab which is
// actually building the scaffold around the drawer.
Widget _buildAndroidHomePage(BuildContext context) {
return SongsTab(
key: songsTabKey,
androidDrawer: _AndroidDrawer(),
);
return SongsTab(key: songsTabKey, androidDrawer: _AndroidDrawer());
}
// On iOS, the app uses a bottom tab paradigm. Here, each tab view sits inside
@@ -91,10 +88,7 @@ class _PlatformAdaptingHomePageState extends State<PlatformAdaptingHomePage> {
label: SongsTab.title,
icon: SongsTab.iosIcon,
),
BottomNavigationBarItem(
label: NewsTab.title,
icon: NewsTab.iosIcon,
),
BottomNavigationBarItem(label: NewsTab.title, icon: NewsTab.iosIcon),
BottomNavigationBarItem(
label: ProfileTab.title,
icon: ProfileTab.iosIcon,
@@ -105,17 +99,17 @@ class _PlatformAdaptingHomePageState extends State<PlatformAdaptingHomePage> {
assert(index <= 2 && index >= 0, 'Unexpected tab index: $index');
return switch (index) {
0 => CupertinoTabView(
defaultTitle: SongsTab.title,
builder: (context) => SongsTab(key: songsTabKey),
),
defaultTitle: SongsTab.title,
builder: (context) => SongsTab(key: songsTabKey),
),
1 => CupertinoTabView(
defaultTitle: NewsTab.title,
builder: (context) => const NewsTab(),
),
defaultTitle: NewsTab.title,
builder: (context) => const NewsTab(),
),
2 => CupertinoTabView(
defaultTitle: ProfileTab.title,
builder: (context) => const ProfileTab(),
),
defaultTitle: ProfileTab.title,
builder: (context) => const ProfileTab(),
),
_ => const SizedBox.shrink(),
};
},
@@ -161,8 +155,10 @@ class _AndroidDrawer extends StatelessWidget {
title: const Text(NewsTab.title),
onTap: () {
Navigator.pop(context);
Navigator.push<void>(context,
MaterialPageRoute(builder: (context) => const NewsTab()));
Navigator.push<void>(
context,
MaterialPageRoute(builder: (context) => const NewsTab()),
);
},
),
ListTile(
@@ -170,8 +166,10 @@ class _AndroidDrawer extends StatelessWidget {
title: const Text(ProfileTab.title),
onTap: () {
Navigator.pop(context);
Navigator.push<void>(context,
MaterialPageRoute(builder: (context) => const ProfileTab()));
Navigator.push<void>(
context,
MaterialPageRoute(builder: (context) => const ProfileTab()),
);
},
),
// Long drawer contents are often segmented.
@@ -184,8 +182,10 @@ class _AndroidDrawer extends StatelessWidget {
title: const Text(SettingsTab.title),
onTap: () {
Navigator.pop(context);
Navigator.push<void>(context,
MaterialPageRoute(builder: (context) => const SettingsTab()));
Navigator.push<void>(
context,
MaterialPageRoute(builder: (context) => const SettingsTab()),
);
},
),
],

View File

@@ -32,8 +32,10 @@ class _NewsTabState extends State<NewsTab> {
void initState() {
colors = getRandomColors(_itemsLength);
titles = List.generate(_itemsLength, (index) => generateRandomHeadline());
contents =
List.generate(_itemsLength, (index) => lorem(paragraphs: 1, words: 24));
contents = List.generate(
_itemsLength,
(index) => lorem(paragraphs: 1, words: 24),
);
super.initState();
}
@@ -44,9 +46,7 @@ class _NewsTabState extends State<NewsTab> {
child: Card(
elevation: 1.5,
margin: const EdgeInsets.fromLTRB(6, 12, 6, 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
child: InkWell(
// Make it splash on Android. It would happen automatically if this
// was a real card but this is just a demo. Skip the splash on iOS.
@@ -76,9 +76,7 @@ class _NewsTabState extends State<NewsTab> {
),
),
const Padding(padding: EdgeInsets.only(top: 8)),
Text(
contents[index],
),
Text(contents[index]),
],
),
),
@@ -96,9 +94,7 @@ class _NewsTabState extends State<NewsTab> {
Widget _buildAndroid(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(NewsTab.title),
),
appBar: AppBar(title: const Text(NewsTab.title)),
body: ListView.builder(
itemCount: _itemsLength,
itemBuilder: _listBuilder,
@@ -118,9 +114,6 @@ class _NewsTabState extends State<NewsTab> {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}

View File

@@ -54,9 +54,7 @@ class ProfileTab extends StatelessWidget {
'Into the darkness',
],
),
Expanded(
child: Container(),
),
Expanded(child: Container()),
const LogOutButton(),
],
),
@@ -71,9 +69,7 @@ class ProfileTab extends StatelessWidget {
Widget _buildAndroid(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(title),
),
appBar: AppBar(title: const Text(title)),
body: _buildBody(context),
);
}
@@ -103,10 +99,7 @@ class ProfileTab extends StatelessWidget {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}
@@ -135,10 +128,7 @@ class PreferenceCard extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.only(top: 40),
child: Center(
child: Text(
content,
style: const TextStyle(fontSize: 48),
),
child: Text(content, style: const TextStyle(fontSize: 48)),
),
),
),
@@ -172,7 +162,8 @@ class PreferenceCard extends StatelessWidget {
class LogOutButton extends StatelessWidget {
static const _logoutMessage = Text(
"You can't actually log out! This is just a demo of how alerts work.");
"You can't actually log out! This is just a demo of how alerts work.",
);
const LogOutButton({super.key});
@@ -252,9 +243,6 @@ class LogOutButton extends StatelessWidget {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}

View File

@@ -91,9 +91,7 @@ class _SettingsTabState extends State<SettingsTab> {
Widget _buildAndroid(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(SettingsTab.title),
),
appBar: AppBar(title: const Text(SettingsTab.title)),
body: _buildList(),
);
}
@@ -107,9 +105,6 @@ class _SettingsTabState extends State<SettingsTab> {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}

View File

@@ -42,8 +42,13 @@ class SongDetailTab extends StatelessWidget {
// to build while the hero transition is mid-flight.
//
// It could either be specified here or in SongsTab.
flightShuttleBuilder: (context, animation, flightDirection,
fromHeroContext, toHeroContext) {
flightShuttleBuilder: (
context,
animation,
flightDirection,
fromHeroContext,
toHeroContext,
) {
return HeroAnimatingSongCard(
song: song,
color: color,
@@ -51,26 +56,24 @@ class SongDetailTab extends StatelessWidget {
);
},
),
const Divider(
height: 0,
color: Colors.grey,
),
const Divider(height: 0, color: Colors.grey),
Expanded(
child: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) => switch (index) {
0 => const Padding(
padding: EdgeInsets.only(left: 15, top: 16, bottom: 8),
child: Text(
'You might also like:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
itemBuilder:
(context, index) => switch (index) {
0 => const Padding(
padding: EdgeInsets.only(left: 15, top: 16, bottom: 8),
child: Text(
'You might also like:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
),
_ => const SongPlaceholderTile(),
},
_ => const SongPlaceholderTile(),
},
),
),
],
@@ -83,10 +86,7 @@ class SongDetailTab extends StatelessWidget {
// ===========================================================================
Widget _buildAndroid(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(song)),
body: _buildBody(),
);
return Scaffold(appBar: AppBar(title: Text(song)), body: _buildBody());
}
Widget _buildIos(BuildContext context) {
@@ -101,9 +101,6 @@ class SongDetailTab extends StatelessWidget {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}

View File

@@ -55,9 +55,10 @@ class _SongsTabState extends State<SongsTab> {
// Show a slightly different color palette. Show poppy-ier colors on iOS
// due to lighter contrasting bars and tone it down on Android.
final color = defaultTargetPlatform == TargetPlatform.iOS
? colors[index]
: colors[index].shade400;
final color =
defaultTargetPlatform == TargetPlatform.iOS
? colors[index]
: colors[index].shade400;
return SafeArea(
top: false,
@@ -68,15 +69,17 @@ class _SongsTabState extends State<SongsTab> {
song: songNames[index],
color: color,
heroAnimation: const AlwaysStoppedAnimation(0),
onPressed: () => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => SongDetailTab(
id: index,
song: songNames[index],
color: color,
onPressed:
() => Navigator.of(context).push<void>(
MaterialPageRoute(
builder:
(context) => SongDetailTab(
id: index,
song: songNames[index],
color: color,
),
),
),
),
),
),
),
);
@@ -114,8 +117,8 @@ class _SongsTabState extends State<SongsTab> {
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () async =>
await _androidRefreshKey.currentState!.show(),
onPressed:
() async => await _androidRefreshKey.currentState!.show(),
),
IconButton(
icon: const Icon(Icons.shuffle),
@@ -146,9 +149,7 @@ class _SongsTabState extends State<SongsTab> {
child: const Icon(CupertinoIcons.shuffle),
),
),
CupertinoSliverRefreshControl(
onRefresh: _refreshData,
),
CupertinoSliverRefreshControl(onRefresh: _refreshData),
SliverSafeArea(
top: false,
sliver: SliverPadding(
@@ -167,9 +168,6 @@ class _SongsTabState extends State<SongsTab> {
@override
Widget build(context) {
return PlatformWidget(
androidBuilder: _buildAndroid,
iosBuilder: _buildIos,
);
return PlatformWidget(androidBuilder: _buildAndroid, iosBuilder: _buildIos);
}
}

View File

@@ -20,13 +20,14 @@ class PlatformWidget extends StatelessWidget {
@override
Widget build(context) {
assert(
defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.iOS,
'Unexpected platform $defaultTargetPlatform');
defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.iOS,
'Unexpected platform $defaultTargetPlatform',
);
return switch (defaultTargetPlatform) {
TargetPlatform.android => androidBuilder(context),
TargetPlatform.iOS => iosBuilder(context),
_ => const SizedBox.shrink()
_ => const SizedBox.shrink(),
};
}
}
@@ -65,8 +66,9 @@ class _PressableCardState extends State<PressableCard>
vsync: this,
duration: const Duration(milliseconds: 40),
);
elevationAnimation =
controller.drive(CurveTween(curve: Curves.easeInOutCubic));
elevationAnimation = controller.drive(
CurveTween(curve: Curves.easeInOutCubic),
);
super.initState();
}
@@ -99,8 +101,10 @@ class _PressableCardState extends State<PressableCard>
// hero animation. You likely want to modularize them more in your own
// app.
child: AnimatedBuilder(
animation:
Listenable.merge([elevationAnimation, widget.flattenAnimation]),
animation: Listenable.merge([
elevationAnimation,
widget.flattenAnimation,
]),
child: widget.child,
builder: (context, child) {
return Transform.scale(
@@ -110,7 +114,7 @@ class _PressableCardState extends State<PressableCard>
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 16) *
flatten,
flatten,
child: PhysicalModel(
elevation:
((1 - elevationAnimation.value) * 10 + 10) * flatten,
@@ -192,7 +196,8 @@ class HeroAnimatingSongCard extends StatelessWidget {
),
// The play button grows in the hero animation.
Padding(
padding: const EdgeInsets.only(bottom: 45) *
padding:
const EdgeInsets.only(bottom: 45) *
(1 - heroAnimation.value),
child: Container(
height: playButtonSize,
@@ -202,8 +207,11 @@ class HeroAnimatingSongCard extends StatelessWidget {
color: Colors.black12,
),
alignment: Alignment.center,
child: Icon(Icons.play_arrow,
size: playButtonSize, color: Colors.black38),
child: Icon(
Icons.play_arrow,
size: playButtonSize,
color: Colors.black38,
),
),
),
],
@@ -234,9 +242,7 @@ class SongPlaceholderTile extends StatelessWidget {
color: Theme.of(context).textTheme.bodyMedium!.color,
width: 130,
),
const Padding(
padding: EdgeInsets.only(left: 12),
),
const Padding(padding: EdgeInsets.only(left: 12)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -342,9 +348,7 @@ void showChoices(BuildContext context, List<String> choices) {
return Center(
child: Text(
choices[index],
style: const TextStyle(
fontSize: 21,
),
style: const TextStyle(fontSize: 21),
),
);
}),

View File

@@ -3,7 +3,7 @@ description: A project showcasing a Flutter app following different platform IA
version: 1.0.0+1
environment:
sdk: ^3.5.0
sdk: ^3.7.0-0
dependencies:
english_words: ^4.0.0