- 23 Feb, 2024 1 commit
-
-
LongCatIsLooong authored
Relands "Changing `TextPainter.getOffsetForCaret` implementation to remove the logarithmic search (#143281)" (reverted in #143801) (#143954) The original PR was reverted because the new caret positioning callpath triggered a skparagraph assert. The assert has been removed. Relanding the PR with no changes applied.
-
- 22 Feb, 2024 1 commit
-
-
Qun Cheng authored
Reverts flutter/flutter#138521
-
- 21 Feb, 2024 1 commit
-
-
auto-submit[bot] authored
Reverts "Changing `TextPainter.getOffsetForCaret` implementation to remove the logarithmic search (#143281)" (#143801) Reverts flutter/flutter#143281 Initiated by: LongCatIsLooong Reason for reverting: https://github.com/flutter/flutter/issues/143797 Original PR Author: LongCatIsLooong Reviewed By: {justinmc, jason-simmons} This change reverts the following previous change: Original Description: The behavior largely remains the same, except: 1. The EOT cursor `(textLength, downstream)` for text ending in the opposite writing direction as the paragraph is now placed at the visual end of the last line. For example, in a LTR paragraph, the EOT cursor for `aA` (lowercase for LTR and uppercase for RTL) is placed to the right of the line: `aA|` (it was `a|A` before). This matches the behavior of most applications that do logical order arrow key navigation instead of visual order navigation. And it makes the navigation order consistent for `aA\naA`: ``` |aA => aA| => aA| => aA => aA => aA aA aA aA |aA aA| aA| (1) (2) (3) (4) (5) (6) ``` This is indeed still pretty confusing as (2) and (3), as well as (5) and (6) are hard to distinguish (when the I beam has a large width they are actually visually distinguishable -- they use the same anchor but one gets painted to the left and the other to the right. I noticed that emacs does the same). But logical order navigation will always be confusing in bidi text, in one way or another. Interestingly there are 3 different behaviors I've observed in chrome: - the chrome download dialog (which I think uses GTK text widgets but not sure which version) gives me 2 cursors when navigating bidi text, and - its HTML fields only show one, and presumably they place the I beam at the **trailing edge** of the character (which makes more sense for backspacing I guess). - On the other hand, its (new) omnibar seems to use visual order arrow navigation Side note: we may need to update the "tap to place the caret here" logic to handle the case where the tap lands outside of the text and the text ends in the opposite writing direction. 2. Removed the logarithmic search. The same could be done using the characters package but when glyphInfo tells you about the baseline location in the future we probably don't need the `getBoxesForRange` call. This should fix https://github.com/flutter/flutter/issues/123424. ## Internal Tests This is going to change the image output of some internal golden tests. I'm planning to merge https://github.com/flutter/flutter/pull/143281 before this to avoid updating the same golden files twice for invalid selections.
-
- 20 Feb, 2024 2 commits
-
-
LongCatIsLooong authored
The behavior largely remains the same, except: 1. The EOT cursor `(textLength, downstream)` for text ending in the opposite writing direction as the paragraph is now placed at the visual end of the last line. For example, in a LTR paragraph, the EOT cursor for `aA` (lowercase for LTR and uppercase for RTL) is placed to the right of the line: `aA|` (it was `a|A` before). This matches the behavior of most applications that do logical order arrow key navigation instead of visual order navigation. And it makes the navigation order consistent for `aA\naA`: ``` |aA => aA| => aA| => aA => aA => aA aA aA aA |aA aA| aA| (1) (2) (3) (4) (5) (6) ``` This is indeed still pretty confusing as (2) and (3), as well as (5) and (6) are hard to distinguish (when the I beam has a large width they are actually visually distinguishable -- they use the same anchor but one gets painted to the left and the other to the right. I noticed that emacs does the same). But logical order navigation will always be confusing in bidi text, in one way or another. Interestingly there are 3 different behaviors I've observed in chrome: - the chrome download dialog (which I think uses GTK text widgets but not sure which version) gives me 2 cursors when navigating bidi text, and - its HTML fields only show one, and presumably they place the I beam at the **trailing edge** of the character (which makes more sense for backspacing I guess). - On the other hand, its (new) omnibar seems to use visual order arrow navigation Side note: we may need to update the "tap to place the caret here" logic to handle the case where the tap lands outside of the text and the text ends in the opposite writing direction. 2. Removed the logarithmic search. The same could be done using the characters package but when glyphInfo tells you about the baseline location in the future we probably don't need the `getBoxesForRange` call. This should fix https://github.com/flutter/flutter/issues/123424. ## Internal Tests This is going to change the image output of some internal golden tests. I'm planning to merge https://github.com/flutter/flutter/pull/143281 before this to avoid updating the same golden files twice for invalid selections.
-
Qun Cheng authored
This PR is to introduce 19 new color roles and deprecate 3 color roles in `ColorScheme`. **Tone-based surface colors** (7 colors): * surfaceBright * surfaceDim * surfaceContainer * surfaceContainerLowest * surfaceContainerLow * surfaceContainerHigh * surfaceContainerHighest **Accent color add-ons** (12 colors): * primary/secondary/tertiary-Fixed * primary/secondary/tertiary-FixedDim * onPrimary/onSecondary/onTertiary-Fixed * onPrimary/onSecondary/onTertiary-FixedVariant **Deprecated colors**: * background -> replaced with surface * onBackground -> replaced with onSurface * surfaceVariant -> replaced with surfaceContainerHighest Please checkout this [design doc](https://docs.google.com/document/d/1ODqivpM_6c490T4j5XIiWCDKo5YqHy78YEFqDm4S8h4/edit?usp=sharing) for more information:) 
-
- 14 Feb, 2024 1 commit
-
-
Bruno Leroux authored
## Description This PR adds more documentation for `TextEditingController(String text)` constructor and it adds one example. https://github.com/flutter/flutter/pull/96245 was a first improvement to the documentation. https://github.com/flutter/flutter/issues/79495 tried to hide the cursor when an invalid selection is set but it was reverted. https://github.com/flutter/flutter/pull/123777 mitigated the issue of having a default invalid selection: it takes care of setting a proper selection when a text field is focused and its controller selection is not initialized. I will try changing the initial selection in another PR, but It will probably break several existing tests. ## Related Issue Fixes https://github.com/flutter/flutter/issues/95978 ## Tests Adds 1 test for the new example.
-
- 13 Feb, 2024 1 commit
-
-
Taha Tesser authored
fixes [Chip widget's avatar padding changing if label text is more than 1 line](https://github.com/flutter/flutter/issues/136892) ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; List<String> strings = [ 'hello good morning', 'hello good morning hello good morning', 'hello good morning hello good morning hello good morning' ]; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ const Text( 'avatarBoxConstraints: null \ndeleteIconBoxConstraints: null', textAlign: TextAlign.center), for (String string in strings) Padding( padding: const EdgeInsets.all(8.0), child: RawChip( label: Container( width: 150, color: Colors.amber, child: Text( string, maxLines: 3, overflow: TextOverflow.ellipsis, ), ), avatar: const Icon(Icons.settings), onDeleted: () {}, ), ), ], ), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ const Text( 'avatarBoxConstraints: BoxConstraints.tightForFinite() \ndeleteIconBoxConstraints: BoxConstraints.tightForFinite()', textAlign: TextAlign.center), for (String string in strings) Padding( padding: const EdgeInsets.all(8.0), child: RawChip( avatarBoxConstraints: const BoxConstraints.tightForFinite(), deleteIconBoxConstraints: const BoxConstraints.tightForFinite(), label: Container( width: 150, color: Colors.amber, child: Text( string, maxLines: 3, overflow: TextOverflow.ellipsis, ), ), avatar: const Icon(Icons.settings), onDeleted: () {}, ), ), ], ), ], ), ), ), ); } } ``` </details> ### Preview  # Example previews  
-
- 12 Feb, 2024 1 commit
-
-
Tirth authored
Adds `iconAlignment` property to `ButtonStyleButton` widget. Fixes #89564 ### Example https://github.com/flutter/flutter/assets/13456345/1b5236c4-5c60-4915-b3c6-0a56c43f8a19
-
- 07 Feb, 2024 2 commits
-
-
Bruno Leroux authored
## Description This PR main purpose is to make progress on the M3 test migration for `InputDecorator` (see https://github.com/flutter/flutter/issues/139076). Before this PR more than 80 of the 156 tests defined in `input_decorator_test.dart` fail on M3. Migrating all those tests in one shot is not easy at all because many failures are related to wrong positionning due to M3 typography changes. Another reason is that several M3 specific changes are required in order to get a proper M3 compliant text field, for instance: - https://github.com/flutter/flutter/issues/142972 - https://github.com/flutter/flutter/issues/141354 Most of the tests were relying on an helper function (`buildInputDecorator`) which had a `useMaterial3` parameter. Unfortunately when `useMaterial3: true `was passed to this function it forced `useMaterial3: false` at the top level but overrided it at a lower level, which was very misleading because people could assume that the tests are ok with M3 (but in fact they were run using M2 typography but have some M3 logic in use). I considered various way to make this change and I finally decided to run all existing tests only on M2 for the moment. Next step will be to move most of those tests to M3. In this PR, I migrated two of these existing tests for illustration. Because many of the existing tests are checking input decorator height, I think it would also make sense to fix https://github.com/flutter/flutter/issues/142972 first. That's why I choosed to include a fix to https://github.com/flutter/flutter/issues/142972 in this PR. A M3 filled `TextField` on Android: | Before this PR | After this PR | |--------|--------| |  |  | ## Related Issue Fixes https://github.com/flutter/flutter/issues/142972 Related to https://github.com/flutter/flutter/issues/139076 ## Tests Updates many existing tests + adds 2 tests related to the fix for https://github.com/flutter/flutter/issues/142972 + adds 1 tests for the M3 migration + move 1 tests related to M3
-
Taha Tesser authored
[Original was reverted due to uncaught analysis failure ](https://github.com/flutter/flutter/pull/142825#issuecomment-1930620085) --- fixes [`showSnackBar` is always replacing `animation` parameter of `SnackBar`](https://github.com/flutter/flutter/issues/141646) ### Code sample preview 
-
- 06 Feb, 2024 2 commits
-
-
auto-submit[bot] authored
Reverts flutter/flutter#142825 Initiated by: zanderso Reason for reverting: Analysis failure closing the engine tree https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8756815302197889649/+/u/Framework_analyze/Framework_analyze/stdout?format=raw Original PR Author: TahaTesser Reviewed By: {HansMuller} This change reverts the following previous change: Original Description: fixes [`showSnackBar` is always replacing `animation` parameter of `SnackBar`](https://github.com/flutter/flutter/issues/141646) ### Code sample preview 
-
Taha Tesser authored
fixes [`showSnackBar` is always replacing `animation` parameter of `SnackBar`](https://github.com/flutter/flutter/issues/141646) ### Code sample preview 
-
- 02 Feb, 2024 1 commit
-
-
Hans Muller authored
Reland https://github.com/flutter/flutter/pull/141818 with a fix for a special case: If only `background` is specified for `TextButton.styleFrom` or `OutlinedButton.styleFrom` it applies the button's disabled state, i.e. as if the same value had been specified for disabledBackgroundColor. The change relative to #141818 is the indicated line below: ```dart final MaterialStateProperty<Color?>? backgroundColorProp = switch ((backgroundColor, disabledBackgroundColor)) { (null, null) => null, (_, null) => MaterialStatePropertyAll<Color?>(backgroundColor), // ADDED THIS LINE (_, _) => _TextButtonDefaultColor(backgroundColor, disabledBackgroundColor), }; ``` This backwards incompatibility cropped up in an internal test, see internal Google issue b/323399158.
-
- 01 Feb, 2024 3 commits
-
-
Tirth authored
Write Tests for API Example of `form.0.dart`. Part of #130459
-
auto-submit[bot] authored
Reverts flutter/flutter#141818 Initiated by: XilaiZhang This change reverts the following previous change: Original Description: Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563. Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter. The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are: ```dart typedef ButtonLayerBuilder = Widget Function( BuildContext context, Set<MaterialState> states, Widget? child ); ``` The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button. ## `backgroundBuilder` Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape. The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.red, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return Ink( decoration: BoxDecoration( gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.red, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors: [ Colors.orange.withOpacity(0.5), Colors.yellow.withOpacity(0.5), ]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: Colors.black, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return Ink( decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(burlapUrl), fit: BoxFit.cover, ), ), child: child, ); }, ), child: Text('Text Button'), ) ``` The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final Color color1 = Colors.blue.withOpacity(0.5); final Color color2 = Colors.orange.withOpacity(0.5); return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( colors: switch (states.contains(MaterialState.hovered)) { true => <Color>[color1, color2], false => <Color>[color2, color1], }, ), ), child: child, ); }, ), child: Text('Text Button'), ) ``` The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: Colors.indigo, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final Color color1 = Colors.blue.withOpacity(0.5); final Color color2 = Colors.orange.withOpacity(0.5); return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( colors: switch (states.contains(MaterialState.hovered)) { true => <Color>[color1, color2], false => <Color>[color2, color1], }, ), ), child: child, ); }, ).copyWith( side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) { if (states.contains(MaterialState.hovered)) { return BorderSide(width: 3, color: Colors.yellow); } return null; // defer to the default }), ), child: Text('Text Button'), ) ``` Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton. ## `foregroundBuilder` Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment]. The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child. This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.  ```dart ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final ColorScheme colorScheme = Theme.of(context).colorScheme; return DecoratedBox( decoration: BoxDecoration( border: states.contains(MaterialState.hovered) ? Border(bottom: BorderSide(color: colorScheme.primary)) : Border(), // essentially "no border" ), child: child, ); }, ), child: Text('Text Button'), ) ``` The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.  ```dart ElevatedButton( onPressed: () { }, style: ElevatedButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final ColorScheme colorScheme = Theme.of(context).colorScheme; return ShaderMask( shaderCallback: (Rect bounds) { return LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: <Color>[ colorScheme.primary, colorScheme.primaryContainer, ], ).createShader(bounds); }, blendMode: BlendMode.srcATop, child: child, ); }, ), child: const Text('Elevated Button'), ) ``` A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url; return AnimatedContainer( width: 100, height: 100, duration: Duration(milliseconds: 300), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(url), fit: BoxFit.contain, ), ), ); }, ), child: Text('No Child'), ) ``` In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.transparent, foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url; if (states.contains(MaterialState.pressed)) { url = smiley2Url; } return AnimatedContainer( width: 100, height: 100, duration: Duration(milliseconds: 300), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(url), fit: BoxFit.contain, ), ), ); }, ), child: Text('No Child'), ) ```
-
Hans Muller authored
Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563. Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter. The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are: ```dart typedef ButtonLayerBuilder = Widget Function( BuildContext context, Set<MaterialState> states, Widget? child ); ``` The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button. ## `backgroundBuilder` Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape. The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.red, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return Ink( decoration: BoxDecoration( gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.red, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors: [ Colors.orange.withOpacity(0.5), Colors.yellow.withOpacity(0.5), ]), ), child: child, ); }, ), child: Text('Text Button'), ) ``` One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: Colors.black, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { return Ink( decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(burlapUrl), fit: BoxFit.cover, ), ), child: child, ); }, ), child: Text('Text Button'), ) ``` The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final Color color1 = Colors.blue.withOpacity(0.5); final Color color2 = Colors.orange.withOpacity(0.5); return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( colors: switch (states.contains(MaterialState.hovered)) { true => <Color>[color1, color2], false => <Color>[color2, color1], }, ), ), child: child, ); }, ), child: Text('Text Button'), ) ``` The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: Colors.indigo, backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final Color color1 = Colors.blue.withOpacity(0.5); final Color color2 = Colors.orange.withOpacity(0.5); return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( colors: switch (states.contains(MaterialState.hovered)) { true => <Color>[color1, color2], false => <Color>[color2, color1], }, ), ), child: child, ); }, ).copyWith( side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) { if (states.contains(MaterialState.hovered)) { return BorderSide(width: 3, color: Colors.yellow); } return null; // defer to the default }), ), child: Text('Text Button'), ) ``` Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton. ## `foregroundBuilder` Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment]. The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child. This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.  ```dart ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final ColorScheme colorScheme = Theme.of(context).colorScheme; return DecoratedBox( decoration: BoxDecoration( border: states.contains(MaterialState.hovered) ? Border(bottom: BorderSide(color: colorScheme.primary)) : Border(), // essentially "no border" ), child: child, ); }, ), child: Text('Text Button'), ) ``` The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.  ```dart ElevatedButton( onPressed: () { }, style: ElevatedButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final ColorScheme colorScheme = Theme.of(context).colorScheme; return ShaderMask( shaderCallback: (Rect bounds) { return LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: <Color>[ colorScheme.primary, colorScheme.primaryContainer, ], ).createShader(bounds); }, blendMode: BlendMode.srcATop, child: child, ); }, ), child: const Text('Elevated Button'), ) ``` A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url; return AnimatedContainer( width: 100, height: 100, duration: Duration(milliseconds: 300), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(url), fit: BoxFit.contain, ), ), ); }, ), child: Text('No Child'), ) ``` In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:  ```dart TextButton( onPressed: () {}, style: TextButton.styleFrom( overlayColor: Colors.transparent, foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) { String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url; if (states.contains(MaterialState.pressed)) { url = smiley2Url; } return AnimatedContainer( width: 100, height: 100, duration: Duration(milliseconds: 300), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(url), fit: BoxFit.contain, ), ), ); }, ), child: Text('No Child'), ) ```
-
- 24 Jan, 2024 1 commit
-
-
Polina Cherkasova authored
Original PR: https://github.com/flutter/flutter/pull/141533 Failure: https://fusion2.corp.google.com/presubmit/601217743/OCL:601217743:BASE:601219708:1706132224874:9a4bcab3/targets Fix: [b/321743868](https://b.corp.google.com/321743868), http://cl/601219001 (added as g3 fix.
-
- 22 Jan, 2024 1 commit
-
-
Jesús S Guerrero authored
Reverts flutter/flutter#141533 b/321743868
-
- 18 Jan, 2024 1 commit
-
-
Polina Cherkasova authored
Fixes https://github.com/flutter/flutter/issues/141119 Original PR: https://github.com/flutter/flutter/pull/141138 Revert: https://github.com/flutter/flutter/pull/141479 Reason for revert: https://fusion2.corp.google.com/presubmit/597877179/OCL:597877179:BASE:597883748:1705084754455:88d992fc/targets Fix: cl/599347719
-
- 12 Jan, 2024 5 commits
-
-
Anis Alibegić authored
Fair amount of typos spotted and fixed. Some of them are in comments, some of them are in code and some of them are in nondart files. There is no need for issues since it's a typo fix. I have doubts about [packages/flutter_tools/lib/src/ios/core_devices.dart](https://github.com/flutter/flutter/compare/master...anisalibegic:flutter:master#diff-fdbc1496b4bbe7e2b445a567fd385677af861c0093774e3d8cc460fdd5b794fa), I have a feeling it might broke some things on the other end, even though it's a typo.
-
auto-submit[bot] authored
Reverts flutter/flutter#141138 Initiated by: itsjustkevin This change reverts the following previous change: Original Description: Fixes https://github.com/flutter/flutter/issues/141119 The change is breaking, because now controller is nullable. Migration path: https://github.com/flutter/website/pull/10033 Packages to fix:
-
Polina Cherkasova authored
-
Mairramer authored
Fixes #140770 and #103124 Adds the possibility of passing a height and width to icons. And also a margin for the distance of the lines between the icons.
-
Qun Cheng authored
-
- 09 Jan, 2024 1 commit
-
-
Taha Tesser authored
fixes [`RouteObserver` example throws an error](https://github.com/flutter/flutter/issues/141078) ### Description This updates the `RouteObserver` example from snippet to Dartpad example and fixes the error when running the code snippet
-
- 03 Jan, 2024 1 commit
-
-
Furkan Acar authored
fixes https://github.com/flutter/flutter/issues/138289 --- SegmentedButtom.styleFrom has been added to the segment button, so there is no longer any need to the button style from the beginning. It works like ElevatedButton.styleFrom only I added selectedForegroundColor, selectedBackgroundColor. In this way, the user will be able to change the color first without checking the MaterialState states. I added tests of the same controls. #129215 I opened this problem myself, but I was rejected because I handled too many items in a PR. For now, I wrote a structure that only handles MaterialStates instead of users. old (still avaliable) <img width="626" alt="image" src="https://github.com/flutter/flutter/assets/65075121/9446b13b-c355-4d20-bda2-c47a23d42d4f"> new (just an option for developer) <img width="483" alt="image" src="https://github.com/flutter/flutter/assets/65075121/0a645257-4c83-4029-9484-bd746c02265f"> ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; /// Flutter code sample for [SegmentedButton]. void main() { runApp(const SegmentedButtonApp()); } enum Calendar { day, week, month, year } class SegmentedButtonApp extends StatefulWidget { const SegmentedButtonApp({super.key}); @override State<SegmentedButtonApp> createState() => _SegmentedButtonAppState(); } class _SegmentedButtonAppState extends State<SegmentedButtonApp> { Calendar calendarView = Calendar.day; @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(useMaterial3: true), home: Scaffold( body: Center( child: SegmentedButton<Calendar>( style: SegmentedButton.styleFrom( foregroundColor: Colors.amber, visualDensity: VisualDensity.comfortable, ), // style: const ButtonStyle( // foregroundColor: MaterialStatePropertyAll<Color>(Colors.deepPurple), // visualDensity: VisualDensity.comfortable, // ), segments: const <ButtonSegment<Calendar>>[ ButtonSegment<Calendar>( value: Calendar.day, label: Text('Day'), icon: Icon(Icons.calendar_view_day)), ButtonSegment<Calendar>( value: Calendar.week, label: Text('Week'), icon: Icon(Icons.calendar_view_week)), ButtonSegment<Calendar>( value: Calendar.month, label: Text('Month'), icon: Icon(Icons.calendar_view_month)), ButtonSegment<Calendar>( value: Calendar.year, label: Text('Year'), icon: Icon(Icons.calendar_today)), ], selected: <Calendar>{calendarView}, onSelectionChanged: (Set<Calendar> newSelection) { setState(() { calendarView = newSelection.first; }); }, ), ), ), ); } } ``` </details>
-
- 11 Dec, 2023 1 commit
-
-
Tirth authored
Tests for `app_bar.0`, `app_bar.1`, `app_bar.2`, `app_bar.3`, `sliver_app_bar.1` and `sliver_app_bar.4` were already present. But directory name was `appbar` rather than `app_bar`. I've renamed the directory to `app_bar` since example files uses that only. Part of #130459
-
- 08 Dec, 2023 1 commit
-
-
Ian Hickson authored
Fixes https://github.com/flutter/flutter/issues/105120 I also exposed the relevant dart:ui types which had the effect of removing a large number of dart:ui imports from examples.
-
- 07 Dec, 2023 1 commit
-
-
Jasper van Riet authored
This PR introduces a new property `exitDuration` to Tooltip, the counterpart to `waitDuration`. The need for this is shown by #136586. This changes the behaviour of `showDuration` on mouse pointer devices. This is because the use cases for the current behaviour on touch screen devices vs mouse pointer devices is fundamentally different. <details> <summary>Demo: tooltip with showDuration set</summary> Tooltip disappears after 100 ms when moving away the mouse. Tooltip will not disappear when hovered. https://github.com/flutter/flutter/assets/5138348/81d36dc9-78e0-4723-a84b-2552843ee181 </details> Currently, when `showDuration` is set, this adjusts the time it takes for the tooltip to hide _after_ a mouse pointer has left the tooltip. This is not the same use case as its effect on touch screen devices, where it dictates how long the tooltip stays on screen after a long press. That is needed because the tooltip takes up screen space and there is not an intuitive way to hide it, whereas when using a mouse users expect to simply have to hover somewhere else. Having the tooltip stay around will look broken. Thus, this PR splits the two use cases. `showDuration` no longer affects mouse pointer devices at all*. There is a precedent for such mouse pointer-only behaviour in `waitDuration`. Instead, I have split up the two use cases and created the new property `exitDuration`, which will still allow for tweaking the time it takes for the tooltip to hide after the user has moved their mouse pointer somewhere else. *Note: Should `showDuration` affect [this line](https://github.com/flutter/flutter/blob/e33d4b86270e3c012ba13d68d6e90f2eabc4912b/packages/flutter/lib/src/material/tooltip.dart#L610)? Fixes #136586. Note: I noticed that when I made the change, no tests were broken. Hopefully, the tests added here help that in the future. I also noticed that in the _existing_ tests, the `waitDuration` tests contain assertions that implicate that it is the role of `waitDuration` to change this behaviour, but that's not currently (nor in the new behaviour) true, so I have fixed those tests.
-
- 06 Dec, 2023 1 commit
-
-
Taha Tesser authored
fixes [Expose animation parameters for the [ExpansionTile] widget](https://github.com/flutter/flutter/issues/138047) ### Description Add `AnimationStyle` to the `ExpansionTile` widget to override the default expand and close animation. Syntax: ```dart child: ExpansionTile( title: const Text('Tap to expand'), expansionAnimationStyle: AnimationStyle( duration: Durations.extralong1, curve: Easing.emphasizedAccelerate, ), children: const <Widget>[FlutterLogo(size: 200)], ), ``` ### Code sample <details> <summary>expand to view the code sample</summary> ```dart // 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 [ExpansionTile] and [AnimationStyle]. void main() { runApp(const ExpansionTileAnimationStyleApp()); } enum AnimationStyles { defaultStyle, custom, none } const List<(AnimationStyles, String)> animationStyleSegments = <(AnimationStyles, String)>[ (AnimationStyles.defaultStyle, 'Default'), (AnimationStyles.custom, 'Custom'), (AnimationStyles.none, 'None'), ]; class ExpansionTileAnimationStyleApp extends StatefulWidget { const ExpansionTileAnimationStyleApp({super.key}); @override State<ExpansionTileAnimationStyleApp> createState() => _ExpansionTileAnimationStyleAppState(); } class _ExpansionTileAnimationStyleAppState extends State<ExpansionTileAnimationStyleApp> { Set<AnimationStyles> _animationStyleSelection = <AnimationStyles>{AnimationStyles.defaultStyle}; AnimationStyle? _animationStyle; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ SegmentedButton<AnimationStyles>( selected: _animationStyleSelection, onSelectionChanged: (Set<AnimationStyles> styles) { setState(() { _animationStyleSelection = styles; switch (styles.first) { case AnimationStyles.defaultStyle: _animationStyle = null; case AnimationStyles.custom: _animationStyle = AnimationStyle( curve: Easing.emphasizedAccelerate, duration: Durations.extralong1, ); case AnimationStyles.none: _animationStyle = AnimationStyle.noAnimation; } }); }, segments: animationStyleSegments .map<ButtonSegment<AnimationStyles>>(((AnimationStyles, String) shirt) { return ButtonSegment<AnimationStyles>(value: shirt.$1, label: Text(shirt.$2)); }) .toList(), ), const SizedBox(height: 20), ExpansionTile( expansionAnimationStyle: _animationStyle, title: const Text('ExpansionTile'), children: const <Widget>[ ListTile(title: Text('Expanded Item 1')), ListTile(title: Text('Expanded Item 2')), ], ) ], ), ), ), ); } } ``` </details> Related to https://github.com/flutter/flutter/pull/138721.
-
- 30 Nov, 2023 1 commit
-
-
Tirth authored
Write Tests for API Examples of `cupertino_text_field.0`, `data_table.0`, `icon_button.2` & `ink_well.0` (#139258) Write Tests for API Examples of `cupertino_text_field.0`, `data_table.0`, `icon_button.2` & `ink_well.0` Note: test for `cupertino_text_field.0` was already there but it was named `cupertino_text_field.0.dart`. I renamed it to `cupertino_text_field.0_test.dart`. Part of #130459
-
- 28 Nov, 2023 1 commit
-
-
Tirth authored
Write Tests for API Examples of `snack_bar.0`, `elevated_button.0`, `stepper.0`, `radio.0`, `filled_button.0`, `outlined_button.0` & `card.0` (#138987) Write Tests for API Examples of `snack_bar.0`, `elevated_button.0`, `stepper.0`, `radio.0`, `filled_button.0`, `outlined_button.0` & `card.0` Part of #130459
-
- 27 Nov, 2023 1 commit
-
-
Jasper van Riet authored
This PR writes tests for a few of the API examples (not all), as requested in #130459. For the test names, I used the existing tests in the `api` folder as guide.
-
- 20 Nov, 2023 1 commit
-
-
Taha Tesser authored
This PR introduces `AnimationStyle`, it is used to override default animation curves and durations in several widgets. fixes [Add the ability to customize MaterialApp theme animation duration](https://github.com/flutter/flutter/issues/78372) fixes [Allow customization of showMenu transition animation curves and duration](https://github.com/flutter/flutter/issues/135638) fixes [`AnimationStyle.noAnimation` needs to replace `AnimatedTheme` with just `Theme` in the `MaterialApp`](https://github.com/flutter/flutter/issues/138618) Here is an example where popup menu curve and transition duration is overridden: ```dart popUpAnimationStyle: AnimationStyle( curve: Easing.emphasizedAccelerate, duration: Durations.medium4, ), ``` Set `AnimationStyle.noAnimation` to disable animation. ```dart return MaterialApp( themeAnimationStyle: AnimationStyle.noAnimation, ``` ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
-
- 17 Nov, 2023 1 commit
-
-
auto-submit[bot] authored
Reverts flutter/flutter#137945 Initiated by: HansMuller This change reverts the following previous change: Original Description: This PR introduces `AnimationStyle`, it is used to override default animation curves and durations in several widgets. fixes [Add the ability to customize MaterialApp theme animation duration](https://github.com/flutter/flutter/issues/78372) fixes [Allow customization of showMenu transition animation curves and duration](https://github.com/flutter/flutter/issues/135638) Here is an example where popup menu curve and transition duration is overriden: ```dart popUpAnimationStyle: AnimationStyle( curve: Easing.emphasizedAccelerate, duration: Durations.medium4, ), ``` Set `AnimationStyle.noAnimation` to disable animation. ```dart return MaterialApp( themeAnimationStyle: AnimationStyle.noAnimation, ```
-
- 16 Nov, 2023 1 commit
-
-
Taha Tesser authored
This PR introduces `AnimationStyle`, it is used to override default animation curves and durations in several widgets. fixes [Add the ability to customize MaterialApp theme animation duration](https://github.com/flutter/flutter/issues/78372) fixes [Allow customization of showMenu transition animation curves and duration](https://github.com/flutter/flutter/issues/135638) Here is an example where popup menu curve and transition duration is overriden: ```dart popUpAnimationStyle: AnimationStyle( curve: Easing.emphasizedAccelerate, duration: Durations.medium4, ), ``` Set `AnimationStyle.noAnimation` to disable animation. ```dart return MaterialApp( themeAnimationStyle: AnimationStyle.noAnimation, ```
-
- 13 Nov, 2023 1 commit
-
-
huycozy authored
### Description This PR intends to update `DraggableScrollableSheet` docs for Web and Desktop platforms. On these platforms, the vertical dragging gesture does not provide natural behavior similar to other desktop applications. By adding a note before the sample code so users are aware that the sample code will not work as expected on Desktop and Web. Also, refer to the instructions if they still want to implement it on these platforms. ### Related issue Fixes https://github.com/flutter/flutter/issues/111372
-
- 07 Nov, 2023 2 commits
-
-
Hans Muller authored
This example shows how to use `AnimationController` and `SlideTransition` to create an animated digit like you might find on a digital clock. New digit values slide into place from below, as the old value slides upwards and out of view. Taps that occur while the controller is already animating cause the controller's `AnimationController.duration` to be reduced so that the visuals don't fall behind. You can try the example here: https://dartpad.dev/?id=9553c20fe0fdb0c5447c1293e02400eb
-
Qun Cheng authored
Currently, `Switch.factory` delegates to `CupertinoSwitch` when platform is iOS or macOS. This PR is to: * have the factory configure the Material `Switch` for the expected look and feel. * introduce `Adaptation` class to customize themes for the adaptive components.
-
- 01 Nov, 2023 1 commit
-
-
Qun Cheng authored
Fixes #119401 This PR is to: * add `Card.filled` and `Card.outlined` factory methods so that we can use tokens for these two types of cards to generate default theme instead of providing hard-corded values in example. * update card.2.dart example. * add test file for card.2.dart example. * fix some mismatch caused by editing the auto-generated defaults by hand in navigation_bar.dart and navigation_drawer.dart.
-