Skip to content

[Android] Add display corner radii support.#179219

Merged
auto-submit[bot] merged 14 commits into
flutter:masterfrom
ksokolovskyi:add-display-corner-radii
Jan 21, 2026
Merged

[Android] Add display corner radii support.#179219
auto-submit[bot] merged 14 commits into
flutter:masterfrom
ksokolovskyi:add-display-corner-radii

Conversation

@ksokolovskyi

Copy link
Copy Markdown
Contributor

Closes #97349
Unblocks #178463

Description

This PR focuses only on the Android side.

As was discussed in #97349, the iOS API for getting display corner radii is private. The only safe way to get the radii values is to generate a lookup table ahead and use its values at runtime. I would be happy to work on the iOS implementation in a separate PR after this lands.

  • Adds displayCornerRadii in the physical pixels to the engine's window metrics
  • Adds displayCornerRadii support on the Android API 31+
  • Adds displayCornerRadii in the logical pixels to the MediaQuery
  • Adds and updates tests

Pre-launch Checklist

@ksokolovskyi ksokolovskyi requested a review from a team as a code owner November 28, 2025 15:08
@github-actions github-actions Bot added platform-android Android applications specifically framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine related. See also e: labels. platform-fuchsia Fuchsia code specifically f: scrolling Viewports, list views, slivers, etc. platform-web Web applications specifically team-android Owned by Android platform team labels Nov 28, 2025

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR adds support for display corner radii on Android. The changes span across the engine and framework to expose this new information. The implementation looks solid, with new APIs in dart:ui and MediaQuery to access the corner radii. Tests have been added to cover the new functionality. I've found a critical issue in the copyWith method in MediaQueryData that will cause a compilation error, and another suggestion to improve API consistency. Please see my detailed comments.

Comment thread packages/flutter/lib/src/widgets/media_query.dart
Comment thread packages/flutter/lib/src/widgets/media_query.dart
@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

Hi @justinmc, I assigned you as a reviewer as you took part in the issue discussion.

Could you please take a look at this PR when you have time?

@gmackall gmackall self-requested a review December 1, 2025 19:25

@mdebbar mdebbar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web stubs look good to me!

@mdebbar mdebbar added the triaged-web Triaged by Web platform team label Dec 3, 2025
@reidbaker reidbaker requested a review from mboetger December 4, 2025 21:45

@mboetger mboetger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android-side plumbing looks good. One question below. Also we'll need someone from the framework to look at this, I believe.

@mboetger mboetger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM from the Android side - please wait to submit until you get LGTMs from the web and framework side though.

@mboetger

mboetger commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

I know why the Google testing is failing - I can fix it. I had to make a similar change in #176063 in the JNI (will need to rebase it if that one lands first).

@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

I know why the Google testing is failing - I can fix it. I had to make a similar change in #176063 in the JNI (will need to rebase it if that one lands first).

Thanks a lot for taking a look at the Google Testing failure!
I will do a rebase after your PR is merged.

@ksokolovskyi ksokolovskyi force-pushed the add-display-corner-radii branch from 426843b to d194b89 Compare December 9, 2025 11:22
@github-actions github-actions Bot added the a: tests "flutter test", flutter_test, or one of our tests label Dec 9, 2025
@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

@mboetger, could you please take a look at why Google Testing failed?

@mboetger

mboetger commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

@mboetger, could you please take a look at why Google Testing failed?

Working on it.

@mboetger mboetger added the team-framework Owned by Framework team label Dec 10, 2025
Comment thread packages/flutter/lib/src/widgets/media_query.dart

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits 👍 Thank you for doing this @ksokolovskyi, it's going to be a big improvement for predictive back!

Is there any reason to think that we couldn't reuse the same mechanism to pass this value from iOS as well some day? Seems like it should work to me but want to make sure.

A major edge case: What about a foldable phone that the user unfolds? Does that change the radius values?

Comment thread engine/src/flutter/lib/ui/platform_dispatcher.dart
Comment thread engine/src/flutter/lib/ui/platform_dispatcher.dart Outdated
Comment on lines +2809 to +2810
@override
String toString() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds great, but Diagnosticable is defined in flutter/lib/src/foundation and thus can't be used in engine layer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Darn you're right.

int get hashCode => Object.hash(topLeft, topRight, bottomRight, bottomLeft);

@override
String toString() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Diagnosticable comment here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible as discussed elsewhere.

0.0, // maxWidth
0.0, // minHeight
0.0, // maxHeight
-1.0, // display corner radius top left

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we're assuming that the radius is always circular. Is that an assumption that the Android and iOS APIs make too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both platforms represent device corner radii as a single scalar value rather than an elliptical X/Y pair.

On Android, the RoundedCorner API specifically defines the corner as a 'quarter circle approximation' and only provides a single getRadius() value.

On iOS, Apple uses 'continuous' curves (squircles) for a smoother look. Still, they are defined by a single radius value available via the private _displayCornerRadius property.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for reassuring me 👍

Comment thread packages/flutter/lib/src/widgets/media_query.dart
@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

Hi @justinmc, thanks a lot for your review!

Is there any reason to think that we couldn't reuse the same mechanism to pass this value from iOS as well some day? Seems like it should work to me but want to make sure.

As was discussed in #97349, the iOS API for getting display corner radii is private. The only safe way to get the radii values is to generate a lookup table ahead and use its values at runtime. I would be happy to work on the iOS implementation in a separate PR after this lands.

A major edge case: What about a foldable phone that the user unfolds? Does that change the radius values?

I don't have a physical foldable device, but I tried to run a demo on the Pixel 9 Pro Fold emulator, and the display corner radius values are updated according to the fold status.

Code sample
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Screen(),
    );
  }
}

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

  @override
  State<Screen> createState() => _ScreenState();
}

class _ScreenState extends State<Screen> with SingleTickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    print('dpr: ${MediaQuery.devicePixelRatioOf(context)}');

    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Center(
          child: DisplayCornerRadiiReactor(),
        ),
      ),
    );
  }
}

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

  @override
  State<DisplayCornerRadiiReactor> createState() =>
      _DisplayCornerRadiiReactorState();
}

class _DisplayCornerRadiiReactorState extends State<DisplayCornerRadiiReactor> {
  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 20,
      children: [
        Text(
          'displayCornerRadii: ${View.of(context).displayCornerRadii}',
          textAlign: TextAlign.center,
          style: TextStyle(fontSize: 20),
        ),
        Text(
          'displayCornerRadii: ${MediaQuery.displayCornerRadiiOf(context)}',
          textAlign: TextAlign.center,
          style: TextStyle(fontSize: 20),
        ),
      ],
    );
  }
}
foldable.mp4

@ksokolovskyi ksokolovskyi requested a review from justinmc January 13, 2026 18:59
@justinmc justinmc requested a review from mdebbar January 16, 2026 23:13

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 . Thanks for the followup. Let's wait for a web review and then this is good to go.

0.0, // maxWidth
0.0, // minHeight
0.0, // maxHeight
-1.0, // display corner radius top left

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for reassuring me 👍

Comment on lines +2809 to +2810
@override
String toString() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Darn you're right.

int get hashCode => Object.hash(topLeft, topRight, bottomRight, bottomLeft);

@override
String toString() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible as discussed elsewhere.

@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

@justinmc thanks for your review!
We already have a LGTM from @mdebbar #179219 (review)
Or you would like to get another look from the web team?

@justinmc

Copy link
Copy Markdown
Contributor

Ah I missed that, sorry 😅 .

I reran one test that appeared to be a flake, otherwise this is ready to land.

@ksokolovskyi ksokolovskyi added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 21, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue Jan 21, 2026
Merged via the queue into flutter:master with commit 697572a Jan 21, 2026
181 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jan 21, 2026
@ksokolovskyi

Copy link
Copy Markdown
Contributor Author

Thanks a lot, everyone, for your reviews and feedback!

engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 22, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 22, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 22, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 23, 2026
flutter-zl pushed a commit to flutter-zl/flutter that referenced this pull request Feb 10, 2026
Closes flutter#97349
Unblocks flutter#178463

### Description

This PR focuses only on the Android side.

As was discussed in flutter#97349, the
iOS API for getting display corner radii is private. The only safe way
to get the radii values is to generate a lookup table ahead and use its
values at runtime. I would be happy to work on the iOS implementation in
a separate PR after this lands.

- Adds `displayCornerRadii` in the physical pixels to the engine's
window metrics
- Adds `displayCornerRadii` support on the Android API 31+
- Adds `displayCornerRadii` in the logical pixels to the `MediaQuery`
- Adds and updates tests

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

<!-- 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: Matt Boetger <matt.boetger@gmail.com>
liuyq pushed a commit to liuyq/flutter that referenced this pull request Apr 3, 2026
refer to commit:
    697572a("[Android] Add display corner radii support. (flutter#179219)")

Signed-off-by: Yongqin Liu <yongqin.liu@linaro.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: tests "flutter test", flutter_test, or one of our tests engine flutter/engine related. See also e: labels. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. platform-android Android applications specifically platform-fuchsia Fuchsia code specifically platform-web Web applications specifically team-android Owned by Android platform team team-framework Owned by Framework team triaged-web Triaged by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal][Android] Add ability to get device RoundedCorner

5 participants