Commit Graph

148 Commits

Author SHA1 Message Date
Taha Tesser
cba689cbf8
Add a custom shape example for AppBar.shape (#146421)
fixes [AppBar shape disappears on AppBar elevation change when scrolling](https://github.com/flutter/flutter/issues/145945)

### Description
This PR adds an example for complete custom app bar for the  `AppBar.shape` property.

### Preview

![Screenshot 2024-04-08 at 14 21 04](https://github.com/flutter/flutter/assets/48603081/ae3eda2b-b709-4652-9f2c-dd7b7dcfeb5c)
2024-04-08 18:42:07 +00:00
Kostia Sokolovskyi
8101f13a35
Add tests for theme_extension.1.dart API example. (#145819)
This PR contributes to https://github.com/flutter/flutter/issues/130459

### Description
- Adds tests for `examples/api/lib/material/theme/theme_extension.1.dart`
2024-04-03 23:39:17 +00:00
Taha Tesser
80d774d8dc
Add DropdownMenu cursor behavior sample (#146133)
fixes [Add `DropdownMenu` cursor behavior sample to  `DropdownMenu.enabled` & `DropdownMenu.requestFocusOnTap`  docs](https://github.com/flutter/flutter/issues/146131)

### Preview
![Screenshot 2024-04-02 at 17 12 43](https://github.com/flutter/flutter/assets/48603081/33865ca0-d48d-4651-9c83-9bdcd6369cb8)
2024-04-03 16:31:06 +00:00
Ian Hickson
950ec1c405
Enhance ColorScheme.fromSeed with a new variant parameter (#144805)
Fixes #144649

This PR is to add an enhancement for `ColorScheme.fromSeed()`.  When we input a brighter color with a high chroma and we want the resulting `ColorScheme` respects the source color, we can achieve this by setting

```dart
ColorScheme.fromSeed(
  seedColor: sourceColor,
  variant: Variant.fidelity,
  ...
)
```

Here is a demo for `ColorScheme` constructed by all 9 variants:
![Screenshot 2024-03-13 at 4 33 02 PM](https://github.com/flutter/flutter/assets/36861262/2cdbe559-67ff-4f8b-bd48-ccff5131b949)
![Screenshot 2024-03-13 at 4 33 07 PM](https://github.com/flutter/flutter/assets/36861262/e6af2362-c501-499b-8880-06a321de91e6)
2024-04-03 15:54:34 +00:00
Kostia Sokolovskyi
e6f078fff5
Add tests for material_state_mouse_cursor.0.dart API example. (#145987)
This PR contributes to https://github.com/flutter/flutter/issues/130459

### Description
- Updates `examples/api/lib/material/material_state/material_state_mouse_cursor.0.dart` to allow enable/disable `ListTile` in tests;
- Adds tests for `examples/api/lib/material/material_state/material_state_mouse_cursor.0.dart`.
2024-04-03 02:39:46 +00:00
Taha Tesser
23687c5260
Add AnimationStyle to showBottomSheet and showModalBottomSheet (#145536)
fixes [Introduce animation customizable with `AnimationStyle` to `BottomSheet`](https://github.com/flutter/flutter/issues/145532)

### Default bottom sheet animation
![00-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/a295b002-b310-4dea-8bc4-23b1d299748c)

### Custom bottom sheet animation
![01-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/8c5c3d5f-e67d-4ed5-880d-f17d262087e1)

### No bottom sheet animation
![02-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/872409d8-8a8d-4db9-b95b-7f96a62cdffc)
2024-03-25 08:39:05 +00:00
Vatsal Bhesaniya
01fc13d9f9
Add helper widget parameter to InputDecoration (#145157)
This pull request introduces a new field named `helper` to the InputDecoration class. This field allows for specifying a widget containing contextual information about the InputDecorator.child's value. Unlike `helperText`, which accepts a plain string, `helper` supports widgets, enabling functionalities like tappable links for further explanation. This change aligns with the established pattern of `error`, `label`, `prefix`, and `suffix`.

fixes [#145163](https://github.com/flutter/flutter/issues/145163)
2024-03-20 20:48:05 +00:00
Elias Elfarri
46cb2d7b01
Write unit tests for API Examples of checkbox.0, checkbox.1 (#144888)
Write unit tests for API Examples of checkbox.0, checkbox.1

Part of  #130459
2024-03-12 16:25:58 +00:00
Hans Muller
52961f761f
Updated the smiley TextButton example again (#144630)
Improved the smiley image TextButton example a little. Handling the case where the `Future.delayed` object that represents the button's one second long action is superseded by a second button press that triggers a new one-second action. This does complicate the example - just a little - but it's a little more robust. In case someone copy-and-pastes the code.

The TextButton example was recently updated: https://github.com/flutter/flutter/pull/144583
2024-03-05 20:57:02 +00:00
Hans Muller
e73e7e2e56
Updated the TextButton image button example artwork (#144583)
Updated the "smiley" TextButton example with new images from Nancy Hu @google.  I also made the example a little more complicated, per the new artwork: now it displays a different image while the button's action pretends to run for a second.

https://github.com/flutter/flutter/assets/1377460/b631a484-4b4f-4e01-ad52-a877fb46ef72
2024-03-05 03:01:40 +00:00
Taha Tesser
ba719bc588
Fix CalendarDatePicker day selection shape and overlay (#144317)
fixes [`DatePickerDialog` date entry hover background and ink splash have different radius](https://github.com/flutter/flutter/issues/141350)
fixes [Ability to customize DatePicker day selection background and overlay shape](https://github.com/flutter/flutter/issues/144220)

### Code sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Builder(builder: (context) {
            return FilledButton(
              onPressed: () {
                showDatePicker(
                  context: context,
                  initialDate: DateTime.now(),
                  firstDate: DateTime.utc(2010),
                  lastDate: DateTime.utc(2030),
                );
              },
              child: const Text('Show Date picker'),
            );
          }),
        ),
      ),
    );
  }
}
```

</details>

### Material DatePicker states specs

![overlay_specs](https://github.com/flutter/flutter/assets/48603081/45ce16cf-7ee9-41e1-a4fa-327de07b78d1)

### Day selection overlay

| Before | After |
| --------------- | --------------- |
| <img src="https://github.com/flutter/flutter/assets/48603081/b529d38d-0232-494b-8bf2-55d28420a245" /> | <img src="https://github.com/flutter/flutter/assets/48603081/c4799559-a7ef-45fd-aed9-aeb386370580"  /> |

### Hover, pressed, highlight preview

| Before | After |
| --------------- | --------------- |
| <video src="https://github.com/flutter/flutter/assets/48603081/8edde82a-7f39-4482-afab-183e1bce5991" /> | <video src="https://github.com/flutter/flutter/assets/48603081/04e1502e-67a4-4b33-973d-463067d70151" /> |

### Using `DatePickerThemeData.dayShape` to customize day selection background and overlay shape

| Before | After |
| --------------- | --------------- |
| <img src="https://github.com/flutter/flutter/assets/48603081/a0c85f58-a69b-4e14-a45d-41e580ceedce"  />  | <img src="https://github.com/flutter/flutter/assets/48603081/db67cee1-d28d-4168-98b8-fd7a9cb70cda" /> | 

### Example preview

![Screenshot 2024-02-29 at 15 07 50](https://github.com/flutter/flutter/assets/48603081/3770ed5c-28bf-4d0a-9514-87e1cd2ce515)
2024-03-01 12:44:29 +00:00
Qun Cheng
0d8eafb006
Reland "Reland - Introduce tone-based surfaces and accent color add-ons - Part 2" (#144273) 2024-02-28 13:55:50 -08:00
auto-submit[bot]
2eee0b5750
Reverts "Reland - Introduce tone-based surfaces and accent color add-ons - Part 2 (#144001)" (#144262)
Reverts flutter/flutter#144001

Initiated by: Piinks

Reason for reverting: Failing goldens at the tip of tree

Original PR Author: QuncCccccc

Reviewed By: {HansMuller}

This change reverts the following previous change:
Original Description:
Reverts flutter/flutter#143973

This is a reland for #138521 with an updated g3fix(cl/605555997). Local test: cl/609608958.
2024-02-27 22:04:18 +00:00
Qun Cheng
871d59221c
Reland - Introduce tone-based surfaces and accent color add-ons - Part 2 (#144001)
Reverts flutter/flutter#143973

This is a reland for #138521 with an updated g3fix(cl/605555997). Local test: cl/609608958.
2024-02-27 20:21:14 +00:00
Qun Cheng
4715216c01
Revert "Introduce tone-based surfaces and accent color add-ons - Part 2" (#143973)
Reverts flutter/flutter#138521
2024-02-22 14:51:28 -08:00
Qun Cheng
a2c7ed95d1
Introduce tone-based surfaces and accent color add-ons - Part 2 (#138521)
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:)

![Screenshot 2024-01-08 at 4 56 51 PM](https://github.com/flutter/flutter/assets/36861262/353cdb4c-6ba9-4435-a518-fd3f67e415f0)
2024-02-20 19:01:50 +00:00
Taha Tesser
ccf42dde88
Introduce avatarBoxConstraints & deleteIconBoxConstraints for the chips (#143302)
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
![Screenshot 2024-02-12 at 14 58 35](https://github.com/flutter/flutter/assets/48603081/5724bd07-7ac7-4987-b992-fa3ab8488273)

# Example previews
![Screenshot 2024-02-12 at 22 15 14](https://github.com/flutter/flutter/assets/48603081/33af472d-3561-47d4-8d0d-e1628de1e0aa)
![Screenshot 2024-02-12 at 22 15 46](https://github.com/flutter/flutter/assets/48603081/3de78b59-5cb6-4fd8-879b-8e204aacb069)
2024-02-13 20:30:53 +00:00
Tirth
10442399fb
Introduce iconAlignment for the buttons with icon (#137348)
Adds `iconAlignment` property to `ButtonStyleButton` widget.

Fixes #89564

### Example

https://github.com/flutter/flutter/assets/13456345/1b5236c4-5c60-4915-b3c6-0a56c43f8a19
2024-02-12 17:08:20 +00:00
Bruno Leroux
6a7baf573e
Fix M3 text field height + initial step for input decorator M3 test migration (#142981)
## 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 |
|--------|--------|
| ![image](https://github.com/flutter/flutter/assets/840911/403225b7-4c91-4aee-b19c-0490447ae7e3) | ![image](https://github.com/flutter/flutter/assets/840911/e96cf786-a9f5-4e15-bcdd-078350ff1608) | 

## 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
2024-02-07 13:57:21 +00:00
Taha Tesser
c539ded64b
[reland] Add AnimationStyle to showSnackBar (#143052)
[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

![Screenshot 2024-02-02 at 21 10 57](https://github.com/flutter/flutter/assets/48603081/66d808f0-d638-4561-b9a4-96d1b93938f4)
2024-02-07 10:26:27 +00:00
auto-submit[bot]
83aca58fa7
Reverts "Add AnimationStyle to showSnackBar" (#143001)
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

![Screenshot 2024-02-02 at 21 10 57](https://github.com/flutter/flutter/assets/48603081/66d808f0-d638-4561-b9a4-96d1b93938f4)
2024-02-06 19:35:19 +00:00
Taha Tesser
0cc381da19
Add AnimationStyle to showSnackBar (#142825)
fixes [`showSnackBar` is always replacing `animation` parameter of `SnackBar`](https://github.com/flutter/flutter/issues/141646)

### Code sample preview

![Screenshot 2024-02-02 at 21 10 57](https://github.com/flutter/flutter/assets/48603081/66d808f0-d638-4561-b9a4-96d1b93938f4)
2024-02-06 18:54:41 +00:00
Hans Muller
c6f2cea65e
Reland: Added ButtonStyle.foregroundBuilder and ButtonStyle.backgroundBuilder (#142762)
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.
2024-02-02 01:48:17 +00:00
auto-submit[bot]
07ca92a69e
Reverts "Added ButtonStyle.foregroundBuilder and ButtonStyle.backgroundBuilder" (#142748)
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:

![opaque-gradient-bg](https://github.com/flutter/flutter/assets/1377460/80df8368-e7cf-49ef-aee7-2776a573644c)

```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.

![ink-gradient-bg](https://github.com/flutter/flutter/assets/1377460/68a49733-f30e-44a1-a948-dc8cc95e1716)

```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. 

![translucent-graident-bg](https://github.com/flutter/flutter/assets/1377460/3b016e1f-200a-4d07-8111-e20d29f18014)

```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.

![burlap-bg](https://github.com/flutter/flutter/assets/1377460/f2f61ab1-10d9-43a4-bd63-beecdce33b45)

```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.

![gradient-flip](https://github.com/flutter/flutter/assets/1377460/c6c6fe26-ae47-445b-b82d-4605d9583bd8)

```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.

![border-gradient-bg](https://github.com/flutter/flutter/assets/1377460/63cffcd3-0dcf-4eb1-aed5-d14adf1e57f6)

```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.

![border-fg](https://github.com/flutter/flutter/assets/1377460/687a3245-fe68-4983-a04e-5fcc77f8aa21)

```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.

![shader_mask_fg](https://github.com/flutter/flutter/assets/1377460/54010f24-e65d-4551-ae58-712135df3d8d)

```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.

![image-button](https://github.com/flutter/flutter/assets/1377460/f5b1a22f-43ce-4be3-8e70-06de4c958380)

```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`:

![image-per-state](https://github.com/flutter/flutter/assets/1377460/7ab9da2f-f661-4374-b395-c2e0c7c4cf13)

```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'),
)
```
2024-02-01 21:11:26 +00:00
Hans Muller
ff6c8f5d37
Added ButtonStyle.foregroundBuilder and ButtonStyle.backgroundBuilder (#141818)
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:

![opaque-gradient-bg](https://github.com/flutter/flutter/assets/1377460/80df8368-e7cf-49ef-aee7-2776a573644c)

```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.

![ink-gradient-bg](https://github.com/flutter/flutter/assets/1377460/68a49733-f30e-44a1-a948-dc8cc95e1716)

```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. 

![translucent-graident-bg](https://github.com/flutter/flutter/assets/1377460/3b016e1f-200a-4d07-8111-e20d29f18014)

```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.

![burlap-bg](https://github.com/flutter/flutter/assets/1377460/f2f61ab1-10d9-43a4-bd63-beecdce33b45)

```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.

![gradient-flip](https://github.com/flutter/flutter/assets/1377460/c6c6fe26-ae47-445b-b82d-4605d9583bd8)

```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.

![border-gradient-bg](https://github.com/flutter/flutter/assets/1377460/63cffcd3-0dcf-4eb1-aed5-d14adf1e57f6)

```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.

![border-fg](https://github.com/flutter/flutter/assets/1377460/687a3245-fe68-4983-a04e-5fcc77f8aa21)

```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.

![shader_mask_fg](https://github.com/flutter/flutter/assets/1377460/54010f24-e65d-4551-ae58-712135df3d8d)

```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.

![image-button](https://github.com/flutter/flutter/assets/1377460/f5b1a22f-43ce-4be3-8e70-06de4c958380)

```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`:

![image-per-state](https://github.com/flutter/flutter/assets/1377460/7ab9da2f-f661-4374-b395-c2e0c7c4cf13)

```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'),
)
```
2024-02-01 00:02:23 +00:00
Anis Alibegić
81d80c587d
Fixed a lot of typos (#141431)
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.
2024-01-12 22:10:25 +00:00
Mairramer
f40a99ce7e
Adds support for StepStyle visual property bundle to the Step widget (#140825)
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.
2024-01-12 16:35:08 +00:00
Furkan Acar
83ac76050d
Add SegmentedButton.styleFrom (#137542)
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>
2024-01-03 21:26:02 +00:00
Tirth
6a61e878a6
Renamed appbar to app_bar directory in API Examples Tests (#139922)
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
2023-12-11 22:54:13 +00:00
Jasper van Riet
3c422dd750
Introduce exitDuration to Tooltip for mouse pointer devices (#138321)
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](e33d4b8627/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.
2023-12-07 21:20:06 +00:00
Taha Tesser
f794cf9d97
Add AnimationStyle to ExpansionTile (#139664)
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.
2023-12-06 16:40:24 +00:00
Tirth
c10787bc6a
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
2023-11-30 20:07:00 +00:00
Tirth
a49ee534c6
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
2023-11-28 23:57:10 +00:00
Jasper van Riet
ec639f359c
Write tests for API examples of BottomNavigationBar and IconButton (#138188)
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.
2023-11-27 17:26:37 +00:00
Taha Tesser
fc917c7184
[Reland] Introduce AnimationStyle (#138721)
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
2023-11-20 15:24:41 -08:00
auto-submit[bot]
0135a3310a
Reverts "Introduce AnimationStyle" (#138628)
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,
```
2023-11-17 16:59:19 +00:00
Taha Tesser
19e284f88f
Introduce AnimationStyle (#137945)
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,
```
2023-11-16 18:33:20 +00:00
Qun Cheng
ed70f4e248
Adaptive Switch (#130425)
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.
2023-11-07 10:26:23 -08:00
Qun Cheng
4a0f261b4e
Add Card.filled and Card.outlined factory methods (#136229)
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.
2023-11-01 23:29:49 +00:00
Greg Spencer
13a0d475f5
Convert menus to use OverlayPortal (#130534)
## Description

This converts the `MenuAnchor` class to use `OverlayPortal` instead of directly using the overlay.

## Related Issues
 - Fixes https://github.com/flutter/flutter/issues/124830

## Tests
 - No tests yet (hence it is a draft)
2023-10-18 20:13:08 +00:00
Renzo Olivares
21ad7122a1
Implement SelectionArea single click/tap gestures (#132682)
This change collapses the selection at the clicked/tapped location on single click down for desktop platforms, and on single click/tap up for mobile platforms to match native.

This is a change from how `SelectionArea` previously worked. Before this change a single click down would clear the selection. From observing a native browser it looks like when tapping on static text the selection is not cleared but collapsed. A user can still attain the selection from static text using the `window.getSelection` API.

https://jsfiddle.net/juepasn3/11/ You can try this demo out here to observe this behavior yourself. When clicking on static text the selection will change.

This change also allows `Paragraph.selections` to return selections that are collapsed. This for testing purposes to confirm where the selection has been collapsed.

Partially fixes: #129583
2023-09-28 01:42:16 +00:00
huycozy
c2b1e483dd
Improve DropdownMenu sample code for requestFocusOnTap on mobile platforms (#134867)
### Description

This PR is to improve `DropdownMenu` sample code. By default, `requestFocusOnTap` is false on mobile platforms. When users run API sample code on mobile platforms, they can not edit the text field and think it is a bug. Although it is detailed at https://api.flutter.dev/flutter/material/DropdownMenu/requestFocusOnTap.html, users often do not pay attention to it.

### Related issue

Fixes https://github.com/flutter/flutter/issues/127672
2023-09-18 08:33:14 +00:00
Chinmay Kabi
4a3ab6828a
Fix DataTable example not being scrollable (#131556) 2023-09-11 18:55:53 -05:00
xubaolin
f4707c2b3d
fix a Scrollbar example crash (#127925)
Fix a scrollbar example crash.
https://api.flutter.dev/flutter/material/Scrollbar-class.html#material.Scrollbar.1
2023-09-08 09:40:49 +00:00
Andrea Cioni
400702d1d6
Add an example for InputChip generated by user input (#130645)
New example for `InputChip` that demonstrate how to create/delete them based on user text inputs.

The sample application shows a custom text area where user can enter text. After the user has typed and hits _Enter_ the text will be replaced with an `InputChip` that contains that text. Is it possible to continue typing and add more chips in this way. All of them will be placed in a scrollable horizontal row. Also is it possible to have suggestion displayed below the text input field in case the typed text match some of the available suggestions.

Issue I'm trying to solve:

- https://github.com/flutter/flutter/issues/128247

**Code structure:**

The example app is composed of 2 main components that find places inside `MainScreen`:

 - `ChipsInput`
 - `ListView`

`ChipsInput` emulates a `TextField` where you can enter text. This text field accepts also a list of values of generic type T (`Topping` in my example), that gets rendered as `InputChip` inside the text field, before the text inserted by the user. This widgets is basically an `InputDecorator` widget that implements `TextInputClient` to get `TextEditingValue` events from the user keyboard. At the end of the input field there is another component, the `TextCursor`, that is displayed just when the user give the focus to the field and emulates the carrets that `TextField` has.

There are also some available callbacks that the user can use to capture events in the `ChipsInput` field like: `onChanged`, `onChipTapped`, `onSubmitted` and `onTextChanged`. This last callback is used to build a list of suggestion that will be placed just below the `ChipsInput` field inside the `ListView`.
2023-09-01 00:02:04 +00:00
Hans Muller
336d60d29c
Updated DropdownMenu example and added a test (#133592) 2023-08-30 14:33:54 -07:00
Hans Muller
4022864c65
Added DropdownMenuEntry.labelWidget (#133491) 2023-08-29 13:01:49 -07:00
Taha Tesser
d8d7e019c1
Add FAB Additional Color Mappings example (#133453)
fixes [Additional color mappings for FAB in Material 3](https://github.com/flutter/flutter/issues/130702)

### Preview
![image](https://github.com/flutter/flutter/assets/48603081/a6f9aef6-af80-41ce-8e59-50f095db047d)
2023-08-29 17:31:02 +00:00
Taha Tesser
1bc791697c
Update default menu text styles for Material 3 (#131930)
Related https://github.com/flutter/flutter/issues/131676

## Description

#### Fix default input text style for `DropdownMenu`

![dropdown_input](https://github.com/flutter/flutter/assets/48603081/301f8243-155a-4b8f-84a8-5e6b7bebb3bc)

### Fix default text style for  `MenuAnchor`'s menu items (which `DropdownMenu` uses for menu items)

![dropdown_item](https://github.com/flutter/flutter/assets/48603081/6b5be81a-72fc-4705-a577-074c7a4cad8f)

###  Default  `DropdownMenu` Input text style 

![Screenshot 2023-08-04 at 16 48 28](https://github.com/flutter/flutter/assets/48603081/bcd9da98-e74d-491e-ae64-6268ae0b3893)

### Default `DropdownMenu` menu item text style

![Screenshot 2023-08-04 at 16 50 19](https://github.com/flutter/flutter/assets/48603081/9592ca43-2854-45b5-8648-203ab65d9745)

### Default `MenuAnchor` menu item text style

![Screenshot 2023-08-04 at 14 34 28](https://github.com/flutter/flutter/assets/48603081/e87e1073-05f8-4dc7-a435-d864e9cce6ab)

### Code sample

<details> 
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

/// Flutter code sample for [DropdownMenu]s. The first dropdown menu has an outlined border.

void main() => runApp(const DropdownMenuExample());

class DropdownMenuExample extends StatefulWidget {
  const DropdownMenuExample({super.key});

  @override
  State<DropdownMenuExample> createState() => _DropdownMenuExampleState();
}

class _DropdownMenuExampleState extends State<DropdownMenuExample> {
  final TextEditingController colorController = TextEditingController();
  final TextEditingController iconController = TextEditingController();
  ColorLabel? selectedColor;
  IconLabel? selectedIcon;

  @override
  Widget build(BuildContext context) {
    final List<DropdownMenuEntry<ColorLabel>> colorEntries =
        <DropdownMenuEntry<ColorLabel>>[];
    for (final ColorLabel color in ColorLabel.values) {
      colorEntries.add(
        DropdownMenuEntry<ColorLabel>(
            value: color, label: color.label, enabled: color.label != 'Grey'),
      );
    }

    final List<DropdownMenuEntry<IconLabel>> iconEntries =
        <DropdownMenuEntry<IconLabel>>[];
    for (final IconLabel icon in IconLabel.values) {
      iconEntries
          .add(DropdownMenuEntry<IconLabel>(value: icon, label: icon.label));
    }

    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.green,
        // textTheme: const TextTheme(
        //   bodyLarge: TextStyle(
        //     fontWeight: FontWeight.bold,
        //     fontStyle: FontStyle.italic,
        //     decoration: TextDecoration.underline,
        //   ),
        // ),
      ),
      home: Scaffold(
        body: SafeArea(
          child: Column(
            children: <Widget>[
              const Text('DropdownMenus'),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 20),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    DropdownMenu<ColorLabel>(
                      controller: colorController,
                      label: const Text('Color'),
                      dropdownMenuEntries: colorEntries,
                      onSelected: (ColorLabel? color) {
                        setState(() {
                          selectedColor = color;
                        });
                      },
                    ),
                    const SizedBox(width: 20),
                    DropdownMenu<IconLabel>(
                      controller: iconController,
                      enableFilter: true,
                      leadingIcon: const Icon(Icons.search),
                      label: const Text('Icon'),
                      dropdownMenuEntries: iconEntries,
                      inputDecorationTheme: const InputDecorationTheme(
                        filled: true,
                        contentPadding: EdgeInsets.symmetric(vertical: 5.0),
                      ),
                      onSelected: (IconLabel? icon) {
                        setState(() {
                          selectedIcon = icon;
                        });
                      },
                    ),
                  ],
                ),
              ),
              const Text('Plain TextFields'),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 20),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    SizedBox(
                      width: 150,
                      child: TextField(
                          controller: TextEditingController(text: 'Blue'),
                          decoration: const InputDecoration(
                            suffixIcon: Icon(Icons.arrow_drop_down),
                            labelText: 'Color',
                            border: OutlineInputBorder(),
                          )),
                    ),
                    const SizedBox(width: 20),
                    SizedBox(
                      width: 150,
                      child: TextField(
                          controller: TextEditingController(text: 'Smile'),
                          decoration: const InputDecoration(
                            prefixIcon: Icon(Icons.search),
                            suffixIcon: Icon(Icons.arrow_drop_down),
                            filled: true,
                            labelText: 'Icon',
                          )),
                    ),
                  ],
                ),
              ),
              if (selectedColor != null && selectedIcon != null)
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                        'You selected a ${selectedColor?.label} ${selectedIcon?.label}'),
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 5),
                      child: Icon(
                        selectedIcon?.icon,
                        color: selectedColor?.color,
                      ),
                    )
                  ],
                )
              else
                const Text('Please select a color and an icon.')
            ],
          ),
        ),
      ),
    );
  }
}

enum ColorLabel {
  blue('Blue', Colors.blue),
  pink('Pink', Colors.pink),
  green('Green', Colors.green),
  yellow('Yellow', Colors.yellow),
  grey('Grey', Colors.grey);

  const ColorLabel(this.label, this.color);
  final String label;
  final Color color;
}

enum IconLabel {
  smile('Smile', Icons.sentiment_satisfied_outlined),
  cloud(
    'Cloud',
    Icons.cloud_outlined,
  ),
  brush('Brush', Icons.brush_outlined),
  heart('Heart', Icons.favorite);

  const IconLabel(this.label, this.icon);
  final String label;
  final IconData icon;
}

``` 
	
</details>
2023-08-22 22:21:00 +00:00
Taha Tesser
af79b4c7a3
Update ExpansionPanel example for the updated expansionCallback callback (#132837)
fixes [ExpansionPanelList can't expand/collapse on the latest stable/master
](https://github.com/flutter/flutter/issues/132759)

https://github.com/flutter/flutter/pull/128082 updated the `expansionCallback` and also the `ExpansionPanel` sample in the Flutter gallery but not the API example. 

This PR fixes the API example and adds tests.
2023-08-21 20:13:22 +00:00