From 96ba3c555afb8bfd5a53ba35e47a7e91943c3167 Mon Sep 17 00:00:00 2001 From: Kostia Sokolovskyi Date: Tue, 24 Sep 2024 02:31:07 +0200 Subject: [PATCH] Add `WidgetStateProperty` example and tests for it. (#155315) This PR contributes to https://github.com/flutter/flutter/issues/155313 ### Description - Adds example for `WidgetStateProperty` - Adds tests for `examples/api/lib/widgets/widget_state/widget_state_property.0.dart` --- .../widget_state/widget_state_property.0.dart | 48 ++++++++++++ .../widget_state_property.0_test.dart | 74 +++++++++++++++++++ .../flutter/lib/src/widgets/widget_state.dart | 10 +++ 3 files changed, 132 insertions(+) create mode 100644 examples/api/lib/widgets/widget_state/widget_state_property.0.dart create mode 100644 examples/api/test/widgets/widget_state/widget_state_property.0_test.dart diff --git a/examples/api/lib/widgets/widget_state/widget_state_property.0.dart b/examples/api/lib/widgets/widget_state/widget_state_property.0.dart new file mode 100644 index 0000000000..bc4d385255 --- /dev/null +++ b/examples/api/lib/widgets/widget_state/widget_state_property.0.dart @@ -0,0 +1,48 @@ +// 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'; + +/// Flutter code sample for [WidgetStateProperty]. + +void main() { + runApp(const WidgetStatePropertyExampleApp()); +} + +class WidgetStatePropertyExampleApp extends StatelessWidget { + const WidgetStatePropertyExampleApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar(title: const Text('WidgetStateProperty Sample')), + body: const Center( + child: WidgetStatePropertyExample(), + ), + ), + ); + } +} + +class WidgetStatePropertyExample extends StatelessWidget { + const WidgetStatePropertyExample({super.key}); + + @override + Widget build(BuildContext context) { + return TextButton( + style: ButtonStyle( + foregroundColor: WidgetStateProperty.fromMap( + { + WidgetState.focused: Colors.blueAccent, + WidgetState.pressed | WidgetState.hovered: Colors.blue, + WidgetState.any: Colors.red, + }, + ), + ), + onPressed: () {}, + child: const Text('TextButton'), + ); + } +} diff --git a/examples/api/test/widgets/widget_state/widget_state_property.0_test.dart b/examples/api/test/widgets/widget_state/widget_state_property.0_test.dart new file mode 100644 index 0000000000..f7086dd899 --- /dev/null +++ b/examples/api/test/widgets/widget_state/widget_state_property.0_test.dart @@ -0,0 +1,74 @@ +// 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 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_api_samples/widgets/widget_state/widget_state_property.0.dart' + as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + Color? getTextColor(WidgetTester tester) { + final BuildContext context = tester.element(find.text('TextButton')); + final TextStyle textStyle = DefaultTextStyle.of(context).style; + + return textStyle.color; + } + + testWidgets('Displays red colored text by default', (WidgetTester tester) async { + await tester.pumpWidget( + const example.WidgetStatePropertyExampleApp(), + ); + + expect(getTextColor(tester), Colors.red); + }); + + testWidgets('Displays blue colored text when button is hovered', (WidgetTester tester) async { + await tester.pumpWidget( + const example.WidgetStatePropertyExampleApp(), + ); + + expect(getTextColor(tester), Colors.red); + + // Hover over the TextButton. + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + await gesture.moveTo(tester.getCenter(find.byType(TextButton))); + + await tester.pumpAndSettle(); + + expect(getTextColor(tester), Colors.blue); + }); + + testWidgets('Displays blue colored text when button is pressed', (WidgetTester tester) async { + await tester.pumpWidget( + const example.WidgetStatePropertyExampleApp(), + ); + + expect(getTextColor(tester), Colors.red); + + // Press on the TextButton. + final TestGesture gesture = await tester.createGesture(); + await gesture.down(tester.getCenter(find.byType(TextButton))); + + await tester.pumpAndSettle(); + + expect(getTextColor(tester), Colors.blue); + }); + + testWidgets('Displays blue colored text when button is focused', (WidgetTester tester) async { + await tester.pumpWidget( + const example.WidgetStatePropertyExampleApp(), + ); + + expect(getTextColor(tester), Colors.red); + + // Focus on the TextButton. + FocusScope.of(tester.element(find.byType(TextButton))).nextFocus(); + + await tester.pumpAndSettle(); + + expect(getTextColor(tester), Colors.blueAccent); + }); +} diff --git a/packages/flutter/lib/src/widgets/widget_state.dart b/packages/flutter/lib/src/widgets/widget_state.dart index 2aadfc39f3..14d46bbc96 100644 --- a/packages/flutter/lib/src/widgets/widget_state.dart +++ b/packages/flutter/lib/src/widgets/widget_state.dart @@ -765,6 +765,16 @@ class _WidgetTextStyleMapper extends WidgetStateTextStyle { /// of their current material state and [resolve] the button style's /// material state properties when their value is needed. /// +/// {@tool dartpad} +/// This example shows how the default text and icon color +/// (the "foreground color") of a [TextButton] can be overridden with a +/// [WidgetStateProperty]. In this example, the button's text color will be +/// `Colors.blue` when the button is being pressed, hovered, or focused. +/// Otherwise, the text color will be `Colors.red`. +/// +/// ** See code in examples/api/lib/widgets/widget_state/widget_state_property.0.dart ** +/// {@end-tool} +/// /// See also: /// /// * [MaterialStateProperty], the Material specific version of