Skip to content

fix: OutlineInputBorder not respecting BorderSide stroke alignment#180487

Merged
auto-submit[bot] merged 6 commits intoflutter:masterfrom
ikramhasan:i_180002
Feb 9, 2026
Merged

fix: OutlineInputBorder not respecting BorderSide stroke alignment#180487
auto-submit[bot] merged 6 commits intoflutter:masterfrom
ikramhasan:i_180002

Conversation

@ikramhasan
Copy link
Contributor

This PR fixes OutlineInputBorder to properly respect the strokeAlign property of BorderSide. Previously, the border was always drawn as if strokeAlign was set to strokeAlignInside, regardless of the actual value specified.

Fixes: #179850

Before:
image

After:

image

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • 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].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Jan 4, 2026
Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request modifies OutlineInputBorder to respect the strokeAlign property of BorderSide. The changes in packages/flutter/lib/src/material/input_border.dart use strokeInset and strokeOffset to adjust the border's dimensions and path based on the alignment. New tests have been added in packages/flutter/test/material/input_decorator_test.dart to verify the behavior for different strokeAlign values. My review includes a suggestion to refactor the new tests to reduce code duplication and improve maintainability, and a minor suggestion to improve test clarity.

Comment on lines +2006 to +2130
testWidgets(
'OutlineInputBorder with BorderSide.strokeAlignOutside should draw border outside bounds',
(WidgetTester tester) async {
const borderWidth = 4.0;
const borderRadius = 12.0;
const inputDecoratorWidth = 800.0;
const inputDecoratorHeight = 56.0;

await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
fillColor: Color(0xFF00FF00),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
borderSide: BorderSide(
width: borderWidth,
strokeAlign: BorderSide.strokeAlignOutside,
),
),
),
),
);

final RenderBox box = tester.renderObject(find.byType(InputDecorator));

expect(
box,
paints..rrect(
style: PaintingStyle.stroke,
strokeWidth: borderWidth,
rrect: RRect.fromLTRBR(
-borderWidth / 2,
-borderWidth / 2,
inputDecoratorWidth + borderWidth / 2,
inputDecoratorHeight + borderWidth / 2,
const Radius.circular(borderRadius + borderWidth / 2),
),
),
);
},
);

testWidgets(
'OutlineInputBorder with BorderSide.strokeAlignCenter should draw border between bounds',
(WidgetTester tester) async {
const borderWidth = 4.0;
const borderRadius = 12.0;
const inputDecoratorWidth = 800.0;
const inputDecoratorHeight = 56.0;

await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
fillColor: Color(0xFF00FF00),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
borderSide: BorderSide(
width: borderWidth,
strokeAlign: BorderSide.strokeAlignCenter,
),
),
),
),
);

final RenderBox box = tester.renderObject(find.byType(InputDecorator));

expect(
box,
paints..rrect(
style: PaintingStyle.stroke,
strokeWidth: borderWidth,
rrect: RRect.fromLTRBR(
0,
0,
inputDecoratorWidth,
inputDecoratorHeight,
const Radius.circular(borderRadius),
),
),
);
},
);

testWidgets(
'OutlineInputBorder with BorderSide.strokeAlignInside should draw border inside bounds',
(WidgetTester tester) async {
const borderWidth = 4.0;
const borderRadius = 12.0;
const inputDecoratorWidth = 800.0;
const inputDecoratorHeight = 56.0;

await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
fillColor: Color(0xFF00FF00),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
borderSide: BorderSide(width: borderWidth),
),
),
),
);

final RenderBox box = tester.renderObject(find.byType(InputDecorator));

expect(
box,
paints..rrect(
style: PaintingStyle.stroke,
strokeWidth: borderWidth,
rrect: RRect.fromLTRBR(
borderWidth / 2,
borderWidth / 2,
inputDecoratorWidth - borderWidth / 2,
inputDecoratorHeight - borderWidth / 2,
const Radius.circular(borderRadius - borderWidth / 2),
),
),
);
},
);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

These three tests for strokeAlign are very similar and contain duplicated code. To improve maintainability and readability, consider refactoring them. One way to do this is to create a group for these tests and use a shared helper function to reduce boilerplate code.

For example, you could create a helper function like this:

Future<void> _testStrokeAlign({
  required WidgetTester tester,
  required double strokeAlign,
  required RRect expectedRRect,
}) async {
  const borderWidth = 4.0;
  const borderRadius = 12.0;
  const inputDecoratorWidth = 800.0;
  const inputDecoratorHeight = 56.0;

  await tester.pumpWidget(
    buildInputDecorator(
      decoration: InputDecoration(
        filled: true,
        fillColor: const Color(0xFF00FF00),
        enabledBorder: OutlineInputBorder(
          borderRadius: const BorderRadius.all(Radius.circular(borderRadius)),
          borderSide: BorderSide(
            width: borderWidth,
            strokeAlign: strokeAlign,
          ),
        ),
      ),
    ),
  );

  final RenderBox box = tester.renderObject(find.byType(InputDecorator));

  expect(
    box,
    paints..rrect(
      style: PaintingStyle.stroke,
      strokeWidth: borderWidth,
      rrect: expectedRRect,
    ),
  );
}

Then, each test would become a simple call to this helper with the specific parameters.

References
  1. The style guide emphasizes optimizing for readability (line 29). While line 30 refers to state, the principle of avoiding duplication is also applicable to test code. Refactoring these tests would align with these principles by making the test suite cleaner and easier to maintain. (link)

fillColor: Color(0xFF00FF00),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
borderSide: BorderSide(width: borderWidth),
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For clarity and to make the test more robust against future changes to default values, it's better to explicitly set strokeAlign: BorderSide.strokeAlignInside here, even though it's the default. This makes the test's intent clearer.

                borderSide: BorderSide(width: borderWidth, strokeAlign: BorderSide.strokeAlignInside),

Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution! I think the change makes sense to me but it seems in the PR description, it shows me the label (the "inside", "center" and "outside") is no longer vertically centered and "outside" label is a bit lower than the border line. We might don't want it to change.

@ikramhasan
Copy link
Contributor Author

Thanks for the contribution! I think the change makes sense to me but it seems in the PR description, it shows me the label (the "inside", "center" and "outside") is no longer vertically centered and "outside" label is a bit lower than the border line. We might don't want it to change.

I actually made a comment regarding this in the issue this PR references. But to note again, the label alignment has not changed. It looks this way because of the decoration moving up or down. I'm not sure if the label is supposed to align with the textfield, or the decoration. Need confirmation on this.

Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

I'm not sure if the label is supposed to align with the textfield, or the decoration. Need confirmation on this.

Yes, the label should align with the border and keep vertically centered.

@ikramhasan
Copy link
Contributor Author

ikramhasan commented Feb 3, 2026

Hey @QuncCccccc, sorry for the late update. I updated the code to make sure the label aligns with the decoration now.

Before After
Before After

Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

Nice fix:) LGTM. Thank you!

Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

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

Thanks for the fix!

@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 7, 2026
@auto-submit
Copy link
Contributor

auto-submit bot commented Feb 7, 2026

autosubmit label was removed for flutter/flutter/180487, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR.

@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Feb 7, 2026
@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 9, 2026
@auto-submit auto-submit bot added this pull request to the merge queue Feb 9, 2026
Merged via the queue into flutter:master with commit a82275c Feb 9, 2026
73 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Feb 9, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 10, 2026
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Feb 10, 2026
Roll Flutter from e8f9dc50356d to 9bda20a11f1e (34 revisions)

flutter/flutter@e8f9dc5...9bda20a

2026-02-10 [email protected] Remove Material import from focus_traversal_test.dart (flutter/flutter#180994)
2026-02-10 [email protected] Roll Skia from 6e217430c052 to cffb3bf918df (1 revision) (flutter/flutter#182131)
2026-02-10 [email protected] Encourage splitting large test files in testing documentation 2 (flutter/flutter#182051)
2026-02-10 [email protected] refactor: migrate CupertinoPageTransitionsBuilder to cupertino folder (flutter/flutter#179776)
2026-02-10 [email protected] Delete the last remaining skia only fragment shader tests (flutter/flutter#182127)
2026-02-10 [email protected] [a11y][android] Set new CheckState APIs for android API 36  (flutter/flutter#182113)
2026-02-10 [email protected] Add missing dependencies to framework_tests_misc_leak_tracking (flutter/flutter#181929)
2026-02-10 [email protected] Roll Dart SDK from eee0e2e11174 to 69eb951f8f7e (2 revisions) (flutter/flutter#182128)
2026-02-10 [email protected] Marks Linux_android_emu android_display_cutout to be flaky (flutter/flutter#181901)
2026-02-10 [email protected] Bump Dart to 3.10 (flutter/flutter#174066)
2026-02-10 [email protected] Roll Skia from d4b7e24a209b to 6e217430c052 (6 revisions) (flutter/flutter#182126)
2026-02-09 [email protected] Intercept UIScene device log and print a guided warning (flutter/flutter#181515)
2026-02-09 [email protected] Introduce ScrollCacheExtent and also fixes unbound shrinkwrap cache ex… (flutter/flutter#181092)
2026-02-09 [email protected] [Android] Add mechanism for setting Android engine flags via Android manifest (take 2) (flutter/flutter#181632)
2026-02-09 [email protected] Fix wrong comment about default impeller value (flutter/flutter#181831)
2026-02-09 [email protected] fix build fail for wayland only platform (flutter/flutter#182057)
2026-02-09 [email protected] [AGP 9] Added Warning Against Updating to AGP 9 (flutter/flutter#181977)
2026-02-09 [email protected] Updated Shaderc dep (flutter/flutter#180976)
2026-02-09 [email protected] Refactor accessibility guidelines out to widget layer (flutter/flutter#181672)
2026-02-09 [email protected] Roll Skia from 68dff53238e5 to d4b7e24a209b (2 revisions) (flutter/flutter#182087)
2026-02-09 [email protected] fix: OutlineInputBorder not respecting BorderSide stroke alignment (flutter/flutter#180487)
2026-02-09 [email protected] Adds opengles to engine dart tests (flutter/flutter#181933)
2026-02-09 [email protected] Add command to build a Swift Package for Add to App and generate FlutterPluginRegistrant (flutter/flutter#181224)
2026-02-09 [email protected] Remove unused constant in `bundle.dart` (flutter/flutter#182023)
2026-02-09 [email protected] Roll Fuchsia Linux SDK from iqtwdXlgKIyZkL5Li... to 7BGf7mPQvgLi7Axb6... (flutter/flutter#182082)
2026-02-09 [email protected] Remove unused getters in `user_messages.dart` (flutter/flutter#181867)
2026-02-09 [email protected] Roll Packages from 7805d3e to 3d5eaa5 (3 revisions) (flutter/flutter#182083)
2026-02-09 [email protected] Roll Skia from 5d891cd7fb7f to 68dff53238e5 (1 revision) (flutter/flutter#182080)
2026-02-09 [email protected] Update example description (flutter/flutter#182067)
2026-02-09 [email protected] Roll Dart SDK from 965b51c219d3 to eee0e2e11174 (1 revision) (flutter/flutter#182073)
2026-02-09 [email protected] Roll Skia from 9533d7533d59 to 5d891cd7fb7f (6 revisions) (flutter/flutter#182070)
2026-02-09 [email protected] Add a new flutter cli command, running-apps, using mDNS app discovery (flutter/flutter#180098)
2026-02-09 [email protected] Roll Skia from b7db9f35f0f2 to 9533d7533d59 (2 revisions) (flutter/flutter#182069)
2026-02-08 [email protected] Improve FlWindowMonitor API (flutter/flutter#181885)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

...
flutter-zl pushed a commit to flutter-zl/flutter that referenced this pull request Feb 10, 2026
…lutter#180487)

This PR fixes `OutlineInputBorder` to properly respect the strokeAlign
property of `BorderSide`. Previously, the border was always drawn as if
strokeAlign was set to strokeAlignInside, regardless of the actual value
specified.

Fixes: flutter#179850

Before: 
<img width="1654" height="444" alt="image"
src="proxy.php?url=https://github.com/user-attachments/assets/98cade3a-34d5-4891-9d2e-2071d461f2b5"
/>

After:

<img width="887" height="241" alt="image"
src="proxy.php?url=https://github.com/user-attachments/assets/11ff3b3e-013f-4a7d-aff5-f21fc64e3e6c"
/>

## 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.
- [x] All existing and new tests are passing.

---------

Co-authored-by: Victor Sanni <[email protected]>
rickhohler pushed a commit to rickhohler/flutter that referenced this pull request Feb 19, 2026
…lutter#180487)

This PR fixes `OutlineInputBorder` to properly respect the strokeAlign
property of `BorderSide`. Previously, the border was always drawn as if
strokeAlign was set to strokeAlignInside, regardless of the actual value
specified.

Fixes: flutter#179850

Before: 
<img width="1654" height="444" alt="image"
src="proxy.php?url=https://github.com/user-attachments/assets/98cade3a-34d5-4891-9d2e-2071d461f2b5"
/>

After:

<img width="887" height="241" alt="image"
src="proxy.php?url=https://github.com/user-attachments/assets/11ff3b3e-013f-4a7d-aff5-f21fc64e3e6c"
/>

## 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.
- [x] All existing and new tests are passing.

---------

Co-authored-by: Victor Sanni <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OutlineInputBorder doesn't respect BorderSide's strokeAlign

3 participants