Unverified Commit 3f5bd7d8 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Add Material 3 `AppBar` example (#102823)

parent 348a2b4f
...@@ -6,24 +6,21 @@ ...@@ -6,24 +6,21 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
void main() => runApp(const MyApp()); void main() => runApp(const AppBarApp());
class MyApp extends StatelessWidget { class AppBarApp extends StatelessWidget {
const MyApp({super.key}); const AppBarApp({super.key});
static const String _title = 'Flutter Code Sample';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const MaterialApp( return const MaterialApp(
title: _title, home: AppBarExample(),
home: MyStatelessWidget(),
); );
} }
} }
class MyStatelessWidget extends StatelessWidget { class AppBarExample extends StatelessWidget {
const MyStatelessWidget({super.key}); const AppBarExample({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
......
...@@ -6,43 +6,120 @@ ...@@ -6,43 +6,120 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
void main() => runApp(const MyApp()); final List<int> _items = List<int>.generate(51, (int index) => index);
class MyApp extends StatelessWidget { void main() => runApp(const AppBarApp());
const MyApp({super.key});
static const String _title = 'Flutter Code Sample'; class AppBarApp extends StatelessWidget {
const AppBarApp({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const MaterialApp( return MaterialApp(
title: _title, theme: ThemeData(
home: MyStatelessWidget(), colorSchemeSeed: const Color(0xff6750a4),
useMaterial3: true,
),
home: const AppBarExample(),
); );
} }
} }
class MyStatelessWidget extends StatelessWidget { class AppBarExample extends StatefulWidget {
const MyStatelessWidget({super.key}); const AppBarExample({super.key});
@override
State<AppBarExample> createState() => _AppBarExampleState();
}
class _AppBarExampleState extends State<AppBarExample> {
bool shadowColor = false;
double? scrolledUnderElevation;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ButtonStyle style = final ColorScheme colorScheme = Theme.of(context).colorScheme;
TextButton.styleFrom(primary: Theme.of(context).colorScheme.onPrimary); final Color oddItemColor = colorScheme.primary.withOpacity(0.05);
final Color evenItemColor = colorScheme.primary.withOpacity(0.15);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
actions: <Widget>[ title: const Text('AppBar Demo'),
TextButton( scrolledUnderElevation: scrolledUnderElevation,
style: style, shadowColor: shadowColor ? Theme.of(context).colorScheme.shadow : null,
onPressed: () {}, ),
child: const Text('Action 1'), body: GridView.builder(
), shrinkWrap: true,
TextButton( itemCount: _items.length,
style: style, padding: const EdgeInsets.all(8.0),
onPressed: () {}, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
child: const Text('Action 2'), crossAxisCount: 3,
childAspectRatio: 2.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
),
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return Center(
child: Text(
'Scroll to see the Appbar in effect.',
style: Theme.of(context).textTheme.labelLarge,
textAlign: TextAlign.center,
),
);
}
return Container(
alignment: Alignment.center,
// tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: _items[index].isOdd ? oddItemColor : evenItemColor,
),
child: Text('Item $index'),
);
},
),
bottomNavigationBar: BottomAppBar(
child: Padding(
padding: const EdgeInsets.all(8),
child: OverflowBar(
overflowAlignment: OverflowBarAlignment.center,
alignment: MainAxisAlignment.center,
overflowSpacing: 5.0,
children: <Widget>[
ElevatedButton.icon(
onPressed: () {
setState(() {
shadowColor = !shadowColor;
});
},
icon: Icon(
shadowColor ? Icons.visibility_off : Icons.visibility,
),
label: const Text('shadow color'),
),
const SizedBox(width: 5),
ElevatedButton.icon(
onPressed: () {
if (scrolledUnderElevation == null) {
setState(() {
// Default elevation is 3.0, increment by 1.0.
scrolledUnderElevation = 4.0;
});
} else {
setState(() {
scrolledUnderElevation = scrolledUnderElevation! + 1.0;
});
}
},
icon: const Icon(Icons.add),
label: Text(
'scrolledUnderElevation: ${scrolledUnderElevation ?? 'default'}',
),
),
],
), ),
], ),
), ),
); );
} }
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for AppBar
import 'package:flutter/material.dart';
void main() => runApp(const AppBarApp());
class AppBarApp extends StatelessWidget {
const AppBarApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: AppBarExample(),
);
}
}
class AppBarExample extends StatelessWidget {
const AppBarExample({super.key});
@override
Widget build(BuildContext context) {
final ButtonStyle style = TextButton.styleFrom(
primary: Theme.of(context).colorScheme.onPrimary,
);
return Scaffold(
appBar: AppBar(
actions: <Widget>[
TextButton(
style: style,
onPressed: () {},
child: const Text('Action 1'),
),
TextButton(
style: style,
onPressed: () {},
child: const Text('Action 2'),
),
],
),
);
}
}
...@@ -6,30 +6,27 @@ ...@@ -6,30 +6,27 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
void main() => runApp(const MyApp()); void main() => runApp(const AppBarApp());
class MyApp extends StatelessWidget { class AppBarApp extends StatelessWidget {
const MyApp({super.key}); const AppBarApp({super.key});
static const String _title = 'Flutter Code Sample';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const MaterialApp( return const MaterialApp(
title: _title, home: SliverAppBarExample(),
home: MyStatefulWidget(),
); );
} }
} }
class MyStatefulWidget extends StatefulWidget { class SliverAppBarExample extends StatefulWidget {
const MyStatefulWidget({super.key}); const SliverAppBarExample({super.key});
@override @override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); State<SliverAppBarExample> createState() => _SliverAppBarExampleState();
} }
class _MyStatefulWidgetState extends State<MyStatefulWidget> { class _SliverAppBarExampleState extends State<SliverAppBarExample> {
bool _pinned = true; bool _pinned = true;
bool _snap = false; bool _snap = false;
bool _floating = false; bool _floating = false;
......
// Copyright 2014 The Flutter Authors. 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';
import 'package:flutter_api_samples/material/app_bar/app_bar.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Appbar updates on navigation', (WidgetTester tester) async {
await tester.pumpWidget(
const example.AppBarApp(),
);
expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget);
expect(find.text('This is the home page'), findsOneWidget);
await tester.tap(find.byIcon(Icons.navigate_next));
await tester.pumpAndSettle();
expect(find.widgetWithText(AppBar, 'Next page'), findsOneWidget);
expect(find.text('This is the next page'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. 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';
import 'package:flutter_api_samples/material/app_bar/app_bar.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
const Offset _kOffset = Offset(0.0, -100.0);
void main() {
testWidgets('Appbar Material 3 test', (WidgetTester tester) async {
await tester.pumpWidget(
const example.AppBarApp()
);
expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget);
Material appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, null);
expect(appbarMaterial.elevation, 0);
await tester.drag(find.text('Item 4'), _kOffset, touchSlopY: 0, warnIfMissed: false);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
await tester.tap(find.text('shadow color'));
await tester.pumpAndSettle();
appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, Colors.black);
expect(appbarMaterial.elevation, 3.0);
await tester.tap(find.text('scrolledUnderElevation: default'));
await tester.pumpAndSettle();
appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, Colors.black);
expect(appbarMaterial.elevation, 4.0);
await tester.tap(find.text('scrolledUnderElevation: 4.0'));
await tester.pumpAndSettle();
appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, Colors.black);
expect(appbarMaterial.elevation, 5.0);
});
}
Material _getAppBarMaterial(WidgetTester tester) {
return tester.widget<Material>(
find.descendant(
of: find.byType(AppBar),
matching: find.byType(Material),
),
);
}
// Copyright 2014 The Flutter Authors. 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';
import 'package:flutter_api_samples/material/app_bar/app_bar.2.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Appbar and actions', (WidgetTester tester) async {
await tester.pumpWidget(
const example.AppBarApp(),
);
expect(find.byType(AppBar), findsOneWidget);
expect(find.widgetWithText(TextButton, 'Action 1'), findsOneWidget);
expect(find.widgetWithText(TextButton, 'Action 2'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. 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';
import 'package:flutter_api_samples/material/app_bar/sliver_app_bar.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
const Offset _kOffset = Offset(0.0, -200.0);
void main() {
testWidgets('SliverAppbar can be pinned', (WidgetTester tester) async {
await tester.pumpWidget(
const example.AppBarApp(),
);
expect(find.widgetWithText(SliverAppBar, 'SliverAppBar'), findsOneWidget);
expect(tester.getBottomLeft(find.text('SliverAppBar')).dy, 144.0);
await tester.drag(find.text('0'), _kOffset, touchSlopY: 0, warnIfMissed: false);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
expect(tester.getBottomLeft(find.text('SliverAppBar')).dy, 40.0);
});
}
...@@ -107,6 +107,15 @@ class _PreferredAppBarSize extends Size { ...@@ -107,6 +107,15 @@ class _PreferredAppBarSize extends Size {
/// ** See code in examples/api/lib/material/app_bar/app_bar.0.dart ** /// ** See code in examples/api/lib/material/app_bar/app_bar.0.dart **
/// {@end-tool} /// {@end-tool}
/// ///
/// Material Design 3 introduced new types of app bar.
/// {@tool dartpad}
/// This sample shows the creation of an [AppBar] widget with the [shadowColor] and
/// [scrolledUnderElevation] properties set, as described in:
/// https://m3.material.io/components/top-app-bar/overview
///
/// ** See code in examples/api/lib/material/app_bar/app_bar.1.dart **
/// {@end-tool}
///
/// ## Troubleshooting /// ## Troubleshooting
/// ///
/// ### Why don't my TextButton actions appear? /// ### Why don't my TextButton actions appear?
...@@ -125,9 +134,10 @@ class _PreferredAppBarSize extends Size { ...@@ -125,9 +134,10 @@ class _PreferredAppBarSize extends Size {
/// [TextButton.style]: /// [TextButton.style]:
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// This sample shows an [AppBar] with two action buttons with their primary
/// color set to [ColorScheme.onPrimary].
/// ///
/// /// ** See code in examples/api/lib/material/app_bar/app_bar.2.dart **
/// ** See code in examples/api/lib/material/app_bar/app_bar.1.dart **
/// {@end-tool} /// {@end-tool}
/// ///
/// See also: /// See also:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment