8497 Commits

Author SHA1 Message Date
Nate Wilson
9ee00ae168
Fix NestedScrollView inner position logic (#157756)
closes #40740

<p align="center">
  <img 
    src="https://github.com/user-attachments/assets/8a48abd0-466b-4e06-90f3-dd05869bac27"
    alt="NestedScrollController fix"
    height="720px"
  />
</p>

<details> <summary><h4>Demo source code</h4> (click to expand)</summary>

(this is a slightly more concise version of the code sample from #40740)

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

void main() {
  runApp(
    const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(body: NewsScreen()),
    ),
  );
}

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

  static const List<String> _tabs = <String>['Featured', 'Popular', 'Latest'];

  static final List<Widget> _tabViews = <Widget>[
    for (final String name in _tabs)
      SafeArea(
        top: false,
        bottom: false,
        child: Builder(builder: (BuildContext context) {
          final handle = NestedScrollView.sliverOverlapAbsorberHandleFor(context);

          return NotificationListener<ScrollNotification>(
            onNotification: (ScrollNotification notification) => true,
            child: CustomScrollView(
              key: PageStorageKey<String>(name),
              slivers: <Widget>[
                SliverOverlapInjector(handle: handle),
                SliverPadding(
                  padding: const EdgeInsets.all(8.0),
                  sliver: SliverList(
                    delegate: SliverChildBuilderDelegate(
                      childCount: 30,
                      (BuildContext context, int index) => Container(
                        margin: const EdgeInsets.only(bottom: 8),
                        width: double.infinity,
                        height: 150,
                        color: const Color(0xFFB0A4C8),
                        alignment: Alignment.center,
                        child: Text(
                          '$name $index',
                          style: const TextStyle(fontWeight: FontWeight.w600),
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          );
        }),
      ),
  ];

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _tabs.length,
      child: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => <Widget>[
          SliverOverlapAbsorber(
            handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
            sliver: SliverSafeArea(
              top: false,
              sliver: SliverAppBar(
                title: const Text('Tab Demo'),
                floating: true,
                pinned: true,
                snap: true,
                forceElevated: innerBoxIsScrolled,
                bottom: TabBar(
                  tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                ),
              ),
            ),
          ),
        ],
        body: TabBarView(children: _tabViews),
      ),
    );
  }
}
```

<br>

</details>

<br>

This bug can be traced to a return statement inside `_NestedScrollPosition`:

```dart
double applyClampedDragUpdate(double delta) {
  // ...
  return delta + offset;
}
```

Thanks to some quirks of floating-point arithmetic, `applyClampedDragUpdate` would sometimes return a tiny non-zero value, which ends up ruining one of the scroll coordinator's equality checks.

8990ed6538/packages/flutter/lib/src/widgets/nested_scroll_view.dart (L658-L664)
2024-11-04 16:42:06 +00:00
Paolo Lammens
d836ca5a68
performance: Override .elementAt in CachingIterable (#152477)
Add a more efficient override of `Iterable.elementAt` in `CachingIterable`.

Closes #152476
2024-11-01 04:50:17 +00:00
Sarbagya Dhaubanjar
19d8fbc6f4
Made insetPadding configurable for Date Picker Dialog (#155651)
This PR adds following properties to the **DatePickerDialog**:
- `insetPadding`
2024-10-31 21:07:08 +00:00
Bruno Leroux
5f65bd06c0
Fix showSnackBar can't access useMaterial3 from the theme (#157707)
## Description

This PR makes it possible for the `MaterialApp` built in `ScaffoldMessenger` state to access the ambient theme.

Before this PR, the built in messenger was above the theme.
After this PR, the build in messenger is below the theme.

## Related Issue

Fixes [Can't access useMaterial3 from the theme in the showSnackBar method](https://github.com/flutter/flutter/issues/115924)

## Tests

Adds 1 test.
2024-10-31 21:04:57 +00:00
chunhtai
b2f72e08ef
Hides added routes before top-most route finishes pushing (#156104)
fixes https://github.com/flutter/flutter/issues/156033
2024-10-31 16:47:55 +00:00
Benji Farquhar
b01558c1cd
Fix cursor on hover expand/collapse icon (#155207) (#155209)
@TahaTesser Fix undesirable side effects of your refactor away from my solution to add `IgnorePointer` during your code review of my PR https://github.com/flutter/flutter/pull/147098. I don't have time to implement my whole initial fix a second time, and update the tests that were added to verify your disabled color change. The issue is resolved with only adding the IgnorePointer.

See [155207](https://github.com/flutter/flutter/issues/155207).
2024-10-31 16:09:18 +00:00
Taha Tesser
b8dcb0c3c5
Update Material 3 LinearProgressIndicator for new visual style (#154817)
Related to [Update both `ProgressIndicator` for Material 3 redesign](https://github.com/flutter/flutter/issues/141340)

### 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 StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isRTL = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(

        body: Directionality(
          textDirection: isRTL ? TextDirection.rtl : TextDirection.ltr,
          child: Center(
            child: Column(
              spacing: 2.0,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text('Default LinearProgressIndicator'),
                const Padding(
                  padding: EdgeInsets.all(16.0),
                  child: LinearProgressIndicator(
                    value: 0.45,
                  ),
                ),
                const Text('Default indefinite LinearProgressIndicator'),
                const Padding(
                  padding: EdgeInsets.all(16.0),
                  child: LinearProgressIndicator(),
                ),
                const Text('Updated height and border radius'),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: LinearProgressIndicator(
                    value: 0.25,
                    minHeight: 16.0,
                    borderRadius: BorderRadius.circular(16.0),
                  ),
                ),
                const Text('Updated stop indicator color and radius'),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: LinearProgressIndicator(
                    value: 0.74,
                    minHeight: 16.0,
                    borderRadius: BorderRadius.circular(16.0),
                    stopIndicatorColor: Theme.of(context).colorScheme.error,
                    stopIndicatorRadius: 32.0,
                  ),
                ),
                const Text('Track gap and stop indicator radius set to 0'),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: LinearProgressIndicator(
                    value: 0.50,
                    minHeight: 16.0,
                    borderRadius: BorderRadius.circular(16.0),
                    trackGap: 0,
                    stopIndicatorRadius: 0,
                  ),
                ),
              ],
            ),
          ),
        ),
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
            setState(() {
              isRTL = !isRTL;
            });
          },
          label:  const Text('Toggle Direction'),
        ),
      ),
    );
  }
}
```

</details>

### Preview

<img width="824" alt="Screenshot 2024-09-09 at 13 53 10" src="https://github.com/user-attachments/assets/d12e56a5-f196-4011-8266-c7ab96be96b2">
2024-10-30 18:14:11 +00:00
Taha Tesser
40c22749f5
Add ability to customize the default Slider padding (#156143)
Fixes [Ability to change Sliders padding](https://github.com/flutter/flutter/issues/40098)

Add ability to override default padding so the Slider can fit better in a layout.

### 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 StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double _sliderValue = 0.5;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        sliderTheme: const SliderThemeData(
          padding: EdgeInsets.symmetric(vertical: 4.0),
          thumbColor: Colors.red,
          inactiveTrackColor: Colors.amber,
        ),
      ),
      home: Scaffold(
        body: Directionality(
          textDirection: TextDirection.ltr,
          child: Center(
            child: Card(
              shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(4.0)),
              ),
              color: Theme.of(context).colorScheme.surfaceContainerHighest,
              margin: const EdgeInsets.symmetric(horizontal: 16.0),
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Placeholder(fallbackHeight: 100.0),
                    Slider(
                      value: _sliderValue,
                      onChanged: (double value) {
                        setState(() {
                          _sliderValue = value;
                        });
                      },
                    ),
                    const Placeholder(fallbackHeight: 100.0),

                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
```

</details>

### Before
(Cannot adjust default `Slider` padding to fill the horizontal space in a `Column` and reduce the padded height)

<img width="717" alt="Screenshot 2024-10-03 at 15 45 18" src="https://github.com/user-attachments/assets/e9d9a4d1-3087-45b4-8607-b94411e2bd23">

### After 
Can adjust default `Slider` padding via `SliderTheme`)

<img width="717" alt="Screenshot 2024-10-03 at 15 46 25" src="https://github.com/user-attachments/assets/cd455881-6d52-46cb-8ac6-cc33f50a13ff">
2024-10-30 10:16:23 +00:00
YeungKC
ec50578982
Fix menu anchor state handling (#157612)
This commit refactors the `_MenuAnchorState` class in `menu_anchor.dart` to include a check for the mounted state and the scheduler phase before calling `setState()`. This ensures that UI updates are only performed when the widget is still mounted and not during the persistent callbacks phase. Additionally, a new test case is added in `menu_anchor_test.dart` to verify that the `isOpen` state of the `MenuAnchor` widget is updated correctly when the button is pressed.

Fix: #157606

*Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.*

*List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.*

*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
2024-10-30 09:42:00 +00:00
yim
c051b69e2a
Add boundary feature to the drag gesture. (#147521)
Inspired by the review on #146182.

This PR adds boundary feature to the drag gestures, including `MultiDragGestureRecognizer` and `DragGestureRecognizer`. The `GestureDetector` widget will also benefit from this.
2024-10-30 03:01:18 +00:00
Taha Tesser
97596e5895
Fix TabBar tab icons not respecting custom IconTheme (#157724)
Fixes [TabBar ignores Theme's iconTheme.size](https://github.com/flutter/flutter/issues/155518)

### Description

When `ThemeData.IconTheme`  with color and size, is provided, it can override the default `Tab` icon color and size. 

### 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(
      theme: ThemeData(
        iconTheme: const IconThemeData(color: Colors.amber, size: 40),
      ),
      home: const Scaffold(
        body: SafeArea(
          child: DefaultTabController(
            length: 2,
            child: Column(
              children: [
                TabBar(
                  tabs: [
                    Tab(icon: Icon(Icons.backpack_outlined), text: 'Backpack'),
                    Tab(icon: Icon(Icons.map_outlined), text: 'Map'),
                  ],
                  overlayColor: WidgetStatePropertyAll(Colors.transparent),
                ),
                Expanded(
                  child: TabBarView(
                    children: [
                      Icon(Icons.backpack_outlined),
                      Icon(Icons.map_outlined),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
```

</details>

---

<img width="666" alt="Screenshot 2024-10-28 at 16 25 06" src="https://github.com/user-attachments/assets/56d31115-7ee9-4378-9811-75a3a2a4ce0f">

<img width="666" alt="Screenshot 2024-10-28 at 16 24 52" src="https://github.com/user-attachments/assets/ab8a3e4b-e912-40ac-b249-6358492581e0">
2024-10-29 10:51:38 +00:00
aniq
c83cf967cf
Allow customizing entry mode icons in TimePicker (#157151)
This PR adds two new properties to the Material Design `TimePicker`: `switchToInputEntryModeIcon` and `switchToTimerEntryModeIcon`. These allow developers to customize the icons for toggling between dial and input modes, with default icons (`Icons.keyboard_outlined` and `Icons.access_time`) used if none are provided.

Fixes #156942
2024-10-29 10:25:20 +00:00
yim
04bcfe9281
Fix Scaffold extend body (#157441)
Fixes: #157316
2024-10-27 04:54:30 +00:00
Polina Cherkasova
9cf98f7273
Create flutter specific leak troubleshooting guidance. (#157396) 2024-10-25 13:25:34 -07:00
Kate Lovett
2c20325af4
Update CupertinoNavigationBar to support large layout (#157133)
Fixes https://github.com/flutter/flutter/issues/149625

This adds a new constructor CupertinoNavigationBar.large for the large style navigation bar. CupertinoSliverNavigationBar enables dynamically changing between the smaller and larger layouts for native iOS headers in response to scrolling, this change makes it possible to configure the static navigation bar in one style or the other.
2024-10-25 19:08:12 +00:00
Jonah Williams
c4c545215a
Support backdrop key in flutter framework. (#157278)
The backdrop key functionality allows multiple backdrop filters to share the same input filter, dramatically improving raster performance. This is only supported on the Impeller backend.

The backdrop key class allocates a new int from a static and passes this to the engine layer. with 64 bit integers, we can allocate many backdrop filter ids per frame and never run out.

See also: https://github.com/flutter/flutter/issues/156455

```dart
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';

final _random = Random();

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

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

  static final listKey = BackdropKey();
  static final overlayKey = BackdropKey();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.white,
        body: Stack(
          children: [
            ListView.builder(
              itemCount: 120, // 60 pairs of red and blue containers
              itemBuilder: (context, index) {
                return Container(
                  height: 100,
                  color: index % 2 == 0 ? Colors.red : Colors.blue,
                );
              },
            ),
            Center(
              child: Container(
                width: 400,
                height: 400,
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.black),
                ),
                child: Image.network('https://picsum.photos/400'),
              ),
            ),
            ListView.separated(
              separatorBuilder: (_, __) => const SizedBox(height: 8),
              itemBuilder: (context, index) => BlurEffect(
                backdropKey: listKey,
                child: SizedBox(
                  height: 50,
                  child: Center(
                    child: Text(index.toString(),
                        style: const TextStyle(color: Colors.white)),
                  ),
                ),
              ),
              itemCount: 200,
            ),
            Positioned.fill(
              bottom: null,
              child: BlurEffect(
                backdropKey: overlayKey,
                child: Padding(
                  padding: EdgeInsets.only(
                    top: MediaQuery.of(context).viewPadding.top,
                  ),
                  child: const SizedBox(height: 45),
                ),
              ),
            ),
            Positioned.fill(
              top: null,
              child: BlurEffect(
                backdropKey: overlayKey,
                child: Padding(
                  padding: EdgeInsets.only(
                    top: MediaQuery.of(context).viewPadding.bottom,
                  ),
                  child: const SizedBox(height: 50),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class BlurEffect extends StatelessWidget {
  final Widget child;

  const BlurEffect({
    required this.child,
    required this.backdropKey,
    super.key,
  });

  final BackdropKey backdropKey;

  @override
  Widget build(BuildContext context) {
    return ClipRect(
      child: BackdropFilter(
        backdropKey: backdropKey,
        filter: ImageFilter.blur(
          sigmaX: 40,
          sigmaY: 40,
          // tileMode: TileMode.mirror,
        ),
        child: DecoratedBox(
          decoration: BoxDecoration(color: Colors.black.withOpacity(.65)),
          child: child,
        ),
      ),
    );
  }
}
```

### Skia

<img src="https://github.com/user-attachments/assets/4c08e92d-f0ba-42b2-a4c4-fc44efbcfae0" width="200"/>

### Impeller

<img src="https://github.com/user-attachments/assets/21e95efd-5e0c-4f41-8f84-af3f0e47d1aa" width="200"/>
2024-10-25 16:27:51 +00:00
Mairramer
8cc862c727
Changes the offset computation to first item for RenderSliverMainAxisGroup (#154688)
Fixes https://github.com/flutter/flutter/issues/154615
When scrolling back to the top, the position of the first visible item should have its scrollExtent subtracted. Otherwise, the accumulated position may be retained, which may result in the first visible item being hidden in some cases.
2024-10-24 19:23:07 +00:00
Huy
fa5254331f
Add ability to disable CupertinoSegmentedControl (#152813)
### Summary

Add the ability to configure enabled or disabled segments in CupertinoSegmentedControl. The idea is to pass a `segmentStates` map, where the user can set the state according to segment key. User can also set background and text colors when the segment is disabled.

### Demo

https://github.com/user-attachments/assets/4a02da02-a0fb-4ded-a271-033a8dc79ac3

### Related issue
Fixes https://github.com/flutter/flutter/issues/52105
2024-10-24 12:05:35 +00:00
LongCatIsLooong
2d3697216b
Turn brieflyShowPassword back on on iOS (#157466)
Fixes https://github.com/flutter/flutter/issues/115359

This patch should restore the `brieflyShowPassword` behavior on iOS before https://github.com/flutter/flutter/pull/104335.

On iOS new characters are still temporarily revealed if the user is entering using the software keyboard (potentially because it's easy to fat finger using on screen keyboards?).
2024-10-23 23:22:15 +00:00
Elliott Brooks
802bae0111
Allow requesting a reduced widget tree with getRootWidgetTree service extension (#157309) 2024-10-23 12:30:55 -07:00
Bruno Leroux
b9c889d7d0
Reland "Fix TextField selects all content after the application is resumed" (#157399)
## Description

Relands https://github.com/flutter/flutter/pull/156968 wich was reverted in https://github.com/flutter/flutter/pull/157378 

This PR makes `EditableText` aware of the lifecycle 'resumed' state to let the current selection unchanged when the application is resumed (on web and desktop, 'resumed' means the Flutter app window regained focus).

Before this PR, on web and desktop, the whole content of a `TextField` was selected whenever a `TextField` gained focus. This is the correct behavior when tabbing between fields but it is not when a field regains focus after the application is resumed 

## Related Issue

Fixes [When switching to another browser tab or window and then going back, all text on TextField is selected automatically](https://github.com/flutter/flutter/issues/156078).

## Tests

Adds 1 test.
2024-10-23 15:13:35 +00:00
Nate Wilson
ea0fda51ef
WidgetStateInputBorder (#157190)
**Changes**
- Add `WidgetStateInputBorder` class, with `.resolveWith()` and `.fromMap()` constructors
- Deprecate `MaterialStateOutlineInputBorder` and `MaterialStateUnderlineInputBorder` and provide data-driven fixes

<br>

**Other changes** based on https://github.com/flutter/flutter/pull/154972#pullrequestreview-2344092821
- Fix documentation copy-paste typo ("OutlinedBorder" → "InputBorder")
- Add test to ensure borders are painted correctly
- Add DartPad sample & relevant test
2024-10-22 23:45:41 +00:00
auto-submit[bot]
60d4c9b741
Reverts "Fix TextField selects all content after the application is resumed (#156968)" (#157378)
Reverts: flutter/flutter#156968
Initiated by: jacobsimionato
Reason for reverting: Google3 roll failing - see b/375019489
Original PR Author: bleroux

Reviewed By: {justinmc, gspencergoog}

This change reverts the following previous change:
## Description

This PR makes `EditableText` aware of the lifecycle 'resumed' state to let the current selection unchanged when the application is resumed (on web and desktop, 'resumed' means the Flutter app window regained focus).

Before this PR, on web and desktop, the whole content of a `TextField` was selected whenever a `TextField` gained focus. This is the correct behavior when tabbing between fields but it is not when a field regains focus after the application is resumed 

## Related Issue

Fixes [When switching to another browser tab or window and then going back, all text on TextField is selected automatically](https://github.com/flutter/flutter/issues/156078).

## Tests

Adds 1 test.
2024-10-22 19:59:22 +00:00
João Victor Schramm
1d5087eb30
fix: CupertinoDatePicker.DateAndTime using showDayOfWeek (#155260)
As mentioned in the issue https://github.com/flutter/flutter/issues/153576, even if we declare the 'showDayOfWeek' value as false, when using the mode CupertinoDatePickerMode.dateAndTime, the days of week still shows in the screen.

This PR is about making an assert that prevent developers from using `DateTimePicker.DateAndTime` with `showDayOfWeek` as false (because it only works on date mode) as suggested by @Piinks.
2024-10-22 19:37:19 +00:00
romain.gyh
21814805c1
fix: Considers strokeAlign to compute border dimensions (#155495)
Fixes #155491 

## 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.
- [ ] 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] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

There are 3 golden tests that don't pass on my computer, but they were
already not passing before my changes.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#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/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Tong Mu <dkwingsmt@users.noreply.github.com>
2024-10-22 12:02:02 -07:00
Bruno Leroux
260bee4d08
Fix MenuController.isOpen throws when unattached (#157331)
## Description

This PR change `MenuController.isOpen` to return false when the `MenuController` is not attached.
Previously `MenuController.isOpen` thrown an assert error when the menu controller was unattached.
With this PR, it is now possible to have some widgets outside the `MenuAnchor` body depending on the menu controller state.

## Related Issue

Fixes [Querying isOpen state for a menu controller that was never attached throws an assertion error](https://github.com/flutter/flutter/issues/157329).

## Tests

Adds 1 test.
2024-10-22 18:49:15 +00:00
Mouad Debbar
e9fb545c05
[web] Allow control of hitTestBehavior of Platform Views (#157189)
Hit testing behavior is currently hardcoded to `opaque`  in `HtmlElementView` which causes the platform view to swallow pointer events when it's a descendant of a `GestureDetector` (see this [example](https://dartpad.dev/?id=5348fbf82be5eeb7d995f953437f0ce6)).

In order to fix this, we need to make `hitTestBehavior` configurable in `HtmlElementView`. This way users can decide to make their platform views `transparent` for hit testing purposes.

**_Note_**: this specific case isn't fixable by `PointerInterceptor` because the framework is already receiving the pointer events, so there's nothing that `PointerInterceptor` can do. This issue is all happening on the framework side since it treats the rectangle occupied by the platform view as an opaque rectangle for hit testing.

**_Workaround_**: in the meantime, users can work around this limitation by surrounding the `HtmlElementView` with an `IgnorePointer` widget.
2024-10-22 17:53:17 +00:00
Jiten Patel
5fa5a64842
[#155269] Platform adaptive showAboutDialog and AboutDialog feature c… (#155377)
This PR introduces a new `showAdaptiveAboutDialog` function, ensuring that the About dialog matches the platform’s design (Material for Android, Fuchsia, Linux, Windows, and, Cupertino for iOS & macOS), providing a more consistent user experience across platforms.

Fixes #155269 

- [] I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
2024-10-22 17:32:05 +00:00
Polina Cherkasova
9edd1ae008
Fix leaks in some image tests and explain hackyness of opted-out. (#154481) 2024-10-22 10:22:01 -07:00
Bruno Leroux
383a221cf3
Fix TextField selects all content after the application is resumed (#156968)
## Description

This PR makes `EditableText` aware of the lifecycle 'resumed' state to let the current selection unchanged when the application is resumed (on web and desktop, 'resumed' means the Flutter app window regained focus).

Before this PR, on web and desktop, the whole content of a `TextField` was selected whenever a `TextField` gained focus. This is the correct behavior when tabbing between fields but it is not when a field regains focus after the application is resumed 

## Related Issue

Fixes to [When switching to another browser tab or window and then going back, all text on TextField is selected automatically](https://github.com/flutter/flutter/issues/156078).

## Tests

To be done
2024-10-22 04:41:31 +00:00
Polina Cherkasova
4b169a81ea
Fix some leaky tests. (#157294) 2024-10-21 21:29:05 +00:00
Parker Lougheed
2336329baf
Resolve pupup menu test TODO (#157251)
Flutter no longer supports versions of Dart that will output the non-reified version.
2024-10-21 19:52:30 +00:00
Parker Lougheed
a0a82f2821
Fix a few typos in framework code and doc comments (#157248) 2024-10-21 19:25:52 +00:00
Taha Tesser
2665a72559
Fix unattached MenuController throws assertion error when calling MenuController.close() (#156588)
Fixes [Closing a menu controller that was never attached throws an assertion error](https://github.com/flutter/flutter/issues/156572)

### 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(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => const MenuControllerPage(),
            ),
          ),
          child: const Text('Press Me'),
        ),
      ),
    );
  }
}

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

  @override
  State<MenuControllerPage> createState() => _MenuControllerPageState();
}

class _MenuControllerPageState extends State<MenuControllerPage> {
  // This menu controller is intentionally left as not attached to a MenuAnchor.
  final MenuController _menuController = MenuController();

  @override
  void dispose() {
    // Close the menu when the page is popped.
    _menuController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          child: const Text('Go back'),
          onPressed: () => Navigator.of(context).pop(),
        ),
      ),
    );
  }
}
```

</details>
2024-10-21 17:26:09 +00:00
Hannes Hultergård
8621694fdf
Add callbacks for detecting tap up events to TapRegion (#156110)
Adds `onTapUpOutside` and `onTapUpInside` callbacks to `TapRegion`, and `onTapUpOutside` to `EditableText` text fields. This allows users to detect `PointerUpEvent`s, which in turn can be used to differentiate between a tap and pan / scroll gesture (for example by comparing the distance between the down and up events).

Fixes #140271 and potentially  #138190
2024-10-21 16:59:16 +00:00
Yegor
cd0aa2b537
all selectable widgets set the hasSelectedState flag (#157191)
Set the `hasSelectedState` flag in all selectable widgets. This happens automatically because only selectable widgets have `Semantics.selected` set to a non-null value. When the value is propagated to `SemanticsConfiguration.isSelected`, it sets both `hasSelectedState` to true and `isSelected` as appropriate.

More progress towards https://github.com/flutter/flutter/issues/66673
2024-10-18 22:37:51 +00:00
Victor Sanni
83a0b85e43
Snap CupertinoSliverNavigationBar large title and bottom widget (#156381)
## Flutter (with this PR):

https://github.com/user-attachments/assets/b0177c06-e4b5-4981-8ec3-62171a4f2547

## Native:

https://github.com/user-attachments/assets/6efa0825-d26c-4c20-81cc-c9fada6e15fc

Fixes https://github.com/flutter/flutter/issues/126028
Fixes https://github.com/flutter/flutter/issues/23321
2024-10-18 19:18:08 +00:00
FMorschel
c40f418c05
Removing unnecessary parenthesis (#156928)
This is simply removing unnecessary parenthesis from various places. This change is because of a change to the unnecessary_parentesis lint that will trigger there. Here is the CL https://dart-review.googlesource.com/c/sdk/+/390161.

- https://github.com/dart-lang/linter/issues/4996

If anything else is needed please let me know. 

I'd like to ask for this PR to wait a bit until the bots are run again on that CL so that I can be sure nothing else will trigger, I will come back here and update this whenever everything is complete. Thanks!
2024-10-17 23:46:25 +00:00
Emmanuel Bonke
77f88ff78a
add dividerThickness in PaginatedDataTable (#156442)
Transitioned from `DataTable` to `PaginatedDataTable` and noted that the latter is missing the `dividerThickness`,  hence this PR adds `dividerThickness` to `PaginatedDataTable`.
2024-10-17 19:43:20 +00:00
Mairramer
6acc5915b4
Fixes TreeSliver collapsing not working (#153438)
This change addresses bug #153418 by ensuring that nodes are handled correctly when closing their children.

Fixes #153418
2024-10-17 18:12:18 +00:00
Lurchfresser
5ce3ae0241
builder gets executed with AnimationStyle.noAnimation (#156982)
Changed the if-statement nesting, so builder gets executed with AnimationStyle.noAnimation.

Pre-launch Checklist

Issue: https://github.com/flutter/flutter/issues/156959

[✅ ] I read the [Contributor Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview) and followed the process outlined there for submitting PRs.
[ ✅] I read the [Tree Hygiene](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md) wiki page, which explains my responsibilities.
[ ✅] I read and followed the [Flutter Style Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md), including [Features we expect every widget to implement](https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement).
[ ✅] I signed the [CLA](https://cla.developers.google.com/).
[ ✅] I listed at least one issue that this PR fixes in the description above.
I updated/added relevant documentation (doc comments with ///).
I added new tests to check the change I am making, or this PR is [test-exempt](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests).
I followed the [breaking change policy](https://github.com/flutter/flutter/blob/main/docs/contributing/Treehygiene.md#handling-breaking-changes) and added [Data Driven Fixes](https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md) where supported.
[✅ ] All existing and new tests are passing.
2024-10-17 17:04:07 +00:00
Crafti
0ce5285051
Implement actionsPadding for AppBar (#155632)
This pull requests adds a new `actionsPadding` property to AppBar, which controls the padding of the actions row's end. By default, no padding is added.

As it was already discussed in the linked issue below (https://github.com/flutter/flutter/issues/115349#issuecomment-1315582192), it is not feasible to change defaults. This PR is an interim solution to allow developers to change layout across the app, until that change/transition can be made (see: the new TODO line). 

Different to the original code from 2018, this PR only adds padding to the actual actions row, instead of the entire `NavigationToolbar`.

Fixes #155747
2024-10-17 13:03:22 +00:00
Yegor
54bf532305
Temporarily skip CustomPainter SemanticsFlag test to allow new flag to roll in (#157061)
Same as https://github.com/flutter/flutter/pull/157017, but for `CustomPainter`.
2024-10-16 22:35:23 +00:00
Yegor
4a57ce7932
Temporarily skip SemanticsFlag test to allow new flag to roll in (#157017)
This test relies on the enumeration of all engine flags, and it will fail when https://github.com/flutter/engine/pull/55780 adds `SemanticsFlag.hasSelectedState`. So temporarily skip the test to allow the new flag to be added. I will later unskip the test and change it to check for the new flag as well.

A step towards https://github.com/flutter/flutter/issues/66673
2024-10-16 20:46:16 +00:00
Nate Wilson
8d1ea1e9c5
Monomorphic Mapper (#154972)
This class looks like it _should_ give valid equality checks:

```dart
class _WidgetStateColorMapper extends _WidgetStateColorTransparent {
  const _WidgetStateColorMapper(this.map);

  final WidgetStateMap<Color> map;

  _WidgetStateMapper<Color> get _mapper => _WidgetStateMapper<Color>(map);

  @override
  Color resolve(Set<WidgetState> states) => _mapper.resolve(states);

  @override
  bool operator ==(Object other) {
    return other is _WidgetStateColorMapper && other.map == map;
  }

  @override
  int get hashCode => map.hashCode;
}
```

But I made a mistake: I should have used `other._mapper == _mapper` and `_mapper.hashCode`.

<br>

It'd be pretty nice if no copy-pasting was needed in the first place:

```dart
class _WidgetStateColorMapper extends WidgetStateMapper<Color> implements WidgetStateColor {
  const _WidgetStateColorMapper(super.map);
}
```

<br><br>

This PR makes `WidgetStateMapper` a public class, similar to `WidgetStatePropertyAll`. The new API, when used incorrectly, will `throw` with a detailed error message, rather than silently returning irrelevant values.
2024-10-16 20:18:28 +00:00
Victor Sanni
f9eebe0319
Add bottom to CupertinoNavigationBar to allow for a double-row nav bar (#155959)
Fixes [Support segmented controls in nav bars and double row nav bars](https://github.com/flutter/flutter/issues/10469)

<img width="270" height="600"  alt="Screenshot 2024-09-30 at 3 09 04 PM" src="https://github.com/user-attachments/assets/4003116f-69dd-4f8f-a185-6ca151b74d2d">
2024-10-16 19:36:55 +00:00
Victor Sanni
293ae2e5ab
Add bottom to CupertinoSliverNavigationBar (#155841)
Fixes [Support search box inside large title nav bar](https://github.com/flutter/flutter/issues/18103)
Part of [Support segmented controls in nav bars and double row nav bars](https://github.com/flutter/flutter/issues/10469)

## None mode (Current default)

https://github.com/user-attachments/assets/d798314e-940f-4311-9a9a-fe999c65f280

## Always mode

https://github.com/user-attachments/assets/950a85aa-8ca2-42ea-bf8b-3cb8f95e616e

## Automatic mode

https://github.com/user-attachments/assets/c7c7240b-d493-4036-a987-30f61d02bac3

## With CupertinoSlidingSegmentedControl

https://github.com/user-attachments/assets/59f4aec4-8d9c-4223-915b-97b73cb25dc8

<details>
<summary>Sample Code</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/cupertino.dart';

/// Flutter code sample for [CupertinoSliverNavigationBar].

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

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

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(brightness: Brightness.light),
      home: SliverNavBarExample(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const CupertinoPageScaffold(
      // A ScrollView that creates custom scroll effects using slivers.
      child: SafeArea(
        child: CustomScrollView(
          // A list of sliver widgets.
          slivers: <Widget>[
            CupertinoSliverNavigationBar(
              leading: SizedBox(
                width: 100,
                child: Row(
                  children: [
                    Icon(CupertinoIcons.back),
                    Text(
                      'Lists',
                      style: TextStyle(color: CupertinoColors.activeBlue),
                    ),
                  ],
                ),
              ),
              trailing: Icon(CupertinoIcons.plus),
              largeTitle: Text('iPhone'),
              // Change to desired mode.
              drawerMode: NavigationDrawerMode.none,
              drawer: Padding(
                padding: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 16.0),
                child: CupertinoSearchTextField(),
              ),
            ),
            SliverFillRemaining(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Text('Drag me up', textAlign: TextAlign.center),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

</details>
2024-10-16 18:25:06 +00:00
Jakub Bogacki
279d30a44f
Add TapOutsideConfiguration widget (#150125)
This PR adds `TapOutsideConfiguration` where you can define a custom default logic for `onTapOutside`.

```dart
TapOutsideConfiguration(
  behavior: AlwaysUnfocusTapOutsideBehavior(),
  // behavior: const NeverUnfocusTapOutsideBehavior(),
  // behavior: const CustomTapOutsideBehavior(),
  child: Column(
    children: [
      // This TextField will use onTapOutside from TapOutsideConfiguration
      TextField(),
      // Of course you can still define onTapOutside
      TextField(onTapOutside: (event) => print('Tapped outside')),
    ],
  ),
)
```

Custom logic can be define like this:

```dart
class CustomTapOutsideBehavior extends TapOutsideBehavior {
  const CustomTapOutsideBehavior();

  @override
  void defaultOnTapOutside(PointerDownEvent event, FocusNode focusNode) {
    // any custom logic here
  }
}
```

This PR implements also two simple `AlwaysUnfocusTapOutsideBehavior` and `NeverUnfocusTapOutsideBehavior`.

Resolves #150123
2024-10-16 13:25:34 +00:00
Bruno Leroux
2430f00a01
fix DropdownMenu keyboard navigation is broken when expandedInsets is set (#156803)
## Description

This PR fixes keyboard navigation when `DropdownMenu.expandedInsets` is used.
Before this PR the Shortcuts widget defining the navigation intents was only added when `DropdownMenu.expandedInsets` was null.
After this PR, the Shortcuts widget is always added.

## Related Issue

Fixes [DropdownMenu keyboard navigation is broken when expandedInsets is set](https://github.com/flutter/flutter/issues/156712).

## Tests

Adds 2 tests.
Replaces several unneeded 'pumpAndSettle'.
2024-10-16 07:30:34 +00:00
Jason Simmons
4f2211b550
Determine the scroll gesture axis based on the effectiveScrollController (#156190)
Fixes https://github.com/flutter/flutter/issues/154520
2024-10-15 20:58:51 +00:00