Skip to content

Commit fefb2b0

Browse files
authored
Re-Land "Refactor StrokeAlign to allow double values." (#108339) (#110234)
1 parent 5705890 commit fefb2b0

32 files changed

+475
-561
lines changed

dev/manual_tests/lib/star_border.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class _MyHomePageState extends State<MyHomePage> {
8080
color: Colors.blue.shade100,
8181
shape: lerpBorder(
8282
StarBorder.polygon(
83-
side: const BorderSide(strokeAlign: StrokeAlign.center, width: 2),
83+
side: const BorderSide(strokeAlign: BorderSide.strokeAlignCenter, width: 2),
8484
sides: _model.points,
8585
pointRounding: _model.pointRounding,
8686
rotation: _model.rotation,
@@ -102,7 +102,7 @@ class _MyHomePageState extends State<MyHomePage> {
102102
color: Colors.blue.shade100,
103103
shape: lerpBorder(
104104
StarBorder(
105-
side: const BorderSide(strokeAlign: StrokeAlign.center, width: 2),
105+
side: const BorderSide(strokeAlign: BorderSide.strokeAlignCenter, width: 2),
106106
points: _model.points,
107107
innerRadiusRatio: _model.innerRadiusRatio,
108108
pointRounding: _model.pointRounding,
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
/// Flutter code sample for [BorderSide.strokeAlign].
6+
7+
import 'package:flutter/material.dart';
8+
9+
void main() => runApp(const StrokeAlignApp());
10+
11+
class StrokeAlignApp extends StatelessWidget {
12+
const StrokeAlignApp({super.key});
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return const MaterialApp(home: StrokeAlignExample());
17+
}
18+
}
19+
20+
class StrokeAlignExample extends StatefulWidget {
21+
const StrokeAlignExample({super.key});
22+
23+
@override
24+
State<StrokeAlignExample> createState() => _StrokeAlignExampleState();
25+
}
26+
27+
class _StrokeAlignExampleState extends State<StrokeAlignExample>
28+
with TickerProviderStateMixin {
29+
late final AnimationController animation;
30+
31+
@override
32+
void initState() {
33+
super.initState();
34+
animation =
35+
AnimationController(vsync: this, duration: const Duration(seconds: 1));
36+
animation.repeat(reverse: true);
37+
animation.addListener(_markDirty);
38+
}
39+
40+
@override
41+
void dispose() {
42+
animation.dispose();
43+
super.dispose();
44+
}
45+
46+
void _markDirty() {
47+
setState(() {});
48+
}
49+
50+
static const double borderWidth = 10;
51+
static const double cornerRadius = 10;
52+
static const Color borderColor = Color(0x8000b4fc);
53+
54+
@override
55+
Widget build(BuildContext context) {
56+
return Material(
57+
child: Center(
58+
child: Column(
59+
mainAxisAlignment: MainAxisAlignment.spaceAround,
60+
children: <Widget>[
61+
BorderedBox(
62+
shape: StadiumBorder(
63+
side: BorderSide(
64+
color: borderColor,
65+
width: borderWidth,
66+
strokeAlign: (animation.value * 2) - 1,
67+
),
68+
),
69+
),
70+
Row(
71+
mainAxisAlignment: MainAxisAlignment.spaceAround,
72+
children: <Widget>[
73+
BorderedBox(
74+
shape: CircleBorder(
75+
side: BorderSide(
76+
color: borderColor,
77+
width: borderWidth,
78+
strokeAlign: (animation.value * 2) - 1,
79+
),
80+
),
81+
),
82+
BorderedBox(
83+
shape: OvalBorder(
84+
side: BorderSide(
85+
color: borderColor,
86+
width: borderWidth,
87+
strokeAlign: (animation.value * 2) - 1,
88+
),
89+
),
90+
),
91+
],
92+
),
93+
Row(
94+
mainAxisAlignment: MainAxisAlignment.spaceAround,
95+
children: <Widget>[
96+
BorderedBox(
97+
shape: BeveledRectangleBorder(
98+
side: BorderSide(
99+
color: borderColor,
100+
width: borderWidth,
101+
strokeAlign: (animation.value * 2) - 1,
102+
),
103+
),
104+
),
105+
BorderedBox(
106+
shape: BeveledRectangleBorder(
107+
borderRadius: BorderRadius.circular(cornerRadius),
108+
side: BorderSide(
109+
color: borderColor,
110+
width: borderWidth,
111+
strokeAlign: (animation.value * 2) - 1,
112+
),
113+
),
114+
),
115+
],
116+
),
117+
Row(
118+
mainAxisAlignment: MainAxisAlignment.spaceAround,
119+
children: <Widget>[
120+
BorderedBox(
121+
shape: RoundedRectangleBorder(
122+
side: BorderSide(
123+
color: borderColor,
124+
width: borderWidth,
125+
strokeAlign: (animation.value * 2) - 1,
126+
),
127+
),
128+
),
129+
BorderedBox(
130+
shape: RoundedRectangleBorder(
131+
borderRadius: BorderRadius.circular(cornerRadius),
132+
side: BorderSide(
133+
color: borderColor,
134+
width: borderWidth,
135+
strokeAlign: (animation.value * 2) - 1,
136+
),
137+
),
138+
),
139+
],
140+
),
141+
Row(
142+
mainAxisAlignment: MainAxisAlignment.spaceAround,
143+
children: <Widget>[
144+
BorderedBox(
145+
shape: StarBorder(
146+
side: BorderSide(
147+
color: borderColor,
148+
width: borderWidth,
149+
strokeAlign: (animation.value * 2) - 1,
150+
),
151+
),
152+
),
153+
BorderedBox(
154+
shape: StarBorder(
155+
pointRounding: 1,
156+
innerRadiusRatio: 0.5,
157+
points: 8,
158+
side: BorderSide(
159+
color: borderColor,
160+
width: borderWidth,
161+
strokeAlign: (animation.value * 2) - 1,
162+
),
163+
),
164+
),
165+
BorderedBox(
166+
shape: StarBorder.polygon(
167+
sides: 6,
168+
pointRounding: 0.5,
169+
side: BorderSide(
170+
color: borderColor,
171+
width: borderWidth,
172+
strokeAlign: (animation.value * 2) - 1,
173+
),
174+
),
175+
),
176+
],
177+
),
178+
],
179+
),
180+
),
181+
);
182+
}
183+
}
184+
185+
class BorderedBox extends StatelessWidget {
186+
const BorderedBox({
187+
super.key,
188+
required this.shape,
189+
});
190+
191+
final ShapeBorder shape;
192+
193+
@override
194+
Widget build(BuildContext context) {
195+
return Container(
196+
width: 100,
197+
height: 50,
198+
decoration: ShapeDecoration(
199+
color: const Color(0xff012677),
200+
shape: shape,
201+
),
202+
);
203+
}
204+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter_api_samples/painting/borders/border_side.stroke_align.0.dart'
7+
as example;
8+
import 'package:flutter_test/flutter_test.dart';
9+
10+
void main() {
11+
testWidgets('Finds the expected BorderedBox', (WidgetTester tester) async {
12+
await tester.pumpWidget(
13+
const MaterialApp(
14+
home: example.StrokeAlignExample(),
15+
),
16+
);
17+
18+
expect(find.byType(example.StrokeAlignExample), findsOneWidget);
19+
expect(find.byType(example.BorderedBox), findsNWidgets(10));
20+
});
21+
}

packages/flutter/lib/src/painting/beveled_rectangle_border.dart

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import 'package:flutter/foundation.dart';
99
import 'basic_types.dart';
1010
import 'border_radius.dart';
1111
import 'borders.dart';
12-
import 'edge_insets.dart';
1312

1413
/// A rectangular border with flattened or "beveled" corners.
1514
///
@@ -40,18 +39,6 @@ class BeveledRectangleBorder extends OutlinedBorder {
4039
/// [getOuterPath].
4140
final BorderRadiusGeometry borderRadius;
4241

43-
@override
44-
EdgeInsetsGeometry get dimensions {
45-
switch (side.strokeAlign) {
46-
case StrokeAlign.inside:
47-
return EdgeInsets.all(side.width);
48-
case StrokeAlign.center:
49-
return EdgeInsets.all(side.width / 2);
50-
case StrokeAlign.outside:
51-
return EdgeInsets.zero;
52-
}
53-
}
54-
5542
@override
5643
ShapeBorder scale(double t) {
5744
return BeveledRectangleBorder(
@@ -125,21 +112,7 @@ class BeveledRectangleBorder extends OutlinedBorder {
125112

126113
@override
127114
Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
128-
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
129-
final RRect adjustedRect;
130-
switch (side.strokeAlign) {
131-
case StrokeAlign.inside:
132-
adjustedRect = borderRect.deflate(side.width);
133-
break;
134-
case StrokeAlign.center:
135-
adjustedRect = borderRect.deflate(side.width / 2);
136-
break;
137-
case StrokeAlign.outside:
138-
adjustedRect = borderRect;
139-
break;
140-
}
141-
142-
return _getPath(adjustedRect);
115+
return _getPath(borderRadius.resolve(textDirection).toRRect(rect).deflate(side.strokeInset));
143116
}
144117

145118
@override
@@ -157,18 +130,7 @@ class BeveledRectangleBorder extends OutlinedBorder {
157130
break;
158131
case BorderStyle.solid:
159132
final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
160-
final RRect adjustedRect;
161-
switch (side.strokeAlign) {
162-
case StrokeAlign.inside:
163-
adjustedRect = borderRect;
164-
break;
165-
case StrokeAlign.center:
166-
adjustedRect = borderRect.inflate(side.width / 2);
167-
break;
168-
case StrokeAlign.outside:
169-
adjustedRect = borderRect.inflate(side.width);
170-
break;
171-
}
133+
final RRect adjustedRect = borderRect.inflate(side.strokeOutset);
172134
final Path path = _getPath(adjustedRect)
173135
..addPath(getInnerPath(rect, textDirection: textDirection), Offset.zero);
174136
canvas.drawPath(path, side.toPaint());

0 commit comments

Comments
 (0)