Skip to content

Commit 86e55df

Browse files
authored
CupertinoFormRow: Add an interactive example (#103041)
* `CupertinoFormRow`: Add an interactive example * fix typo * Update docs
1 parent 81fd748 commit 86e55df

File tree

3 files changed

+166
-42
lines changed

3 files changed

+166
-42
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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 CupertinoFormRow
6+
7+
import 'package:flutter/cupertino.dart';
8+
9+
void main() => runApp(const CupertinoFormRowApp());
10+
11+
class CupertinoFormRowApp extends StatelessWidget {
12+
const CupertinoFormRowApp({Key? key}) : super(key: key);
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return const CupertinoApp(
17+
theme: CupertinoThemeData(brightness: Brightness.light),
18+
home: CupertinoFormRowExample(),
19+
);
20+
}
21+
}
22+
23+
class CupertinoFormRowExample extends StatefulWidget {
24+
const CupertinoFormRowExample({Key? key}) : super(key: key);
25+
26+
@override
27+
State<CupertinoFormRowExample> createState() => _CupertinoFormRowExampleState();
28+
}
29+
30+
class _CupertinoFormRowExampleState extends State<CupertinoFormRowExample> {
31+
bool airplaneMode = false;
32+
33+
@override
34+
Widget build(BuildContext context) {
35+
return CupertinoPageScaffold(
36+
child: CupertinoFormSection(
37+
header: const Text('Connectivity'),
38+
children: <Widget>[
39+
CupertinoFormRow(
40+
prefix: const PrefixWidget(
41+
icon: CupertinoIcons.airplane,
42+
title: 'Airplane Mode',
43+
color: CupertinoColors.systemOrange,
44+
),
45+
child: CupertinoSwitch(
46+
value: airplaneMode,
47+
onChanged: (bool value) {
48+
setState(() {
49+
airplaneMode = value;
50+
});
51+
},
52+
),
53+
),
54+
CupertinoFormRow(
55+
prefix: const PrefixWidget(
56+
icon: CupertinoIcons.wifi,
57+
title: 'Wi-Fi',
58+
color: CupertinoColors.systemBlue,
59+
),
60+
error: const Text('Home network unavailable'),
61+
child: Row(
62+
mainAxisAlignment: MainAxisAlignment.end,
63+
children: const <Widget>[
64+
Text('Not connected'),
65+
SizedBox(width: 5),
66+
Icon(CupertinoIcons.forward)
67+
],
68+
),
69+
),
70+
CupertinoFormRow(
71+
prefix: const PrefixWidget(
72+
icon: CupertinoIcons.bluetooth,
73+
title: 'Bluetooth',
74+
color: CupertinoColors.activeBlue,
75+
),
76+
helper: Padding(
77+
padding: const EdgeInsets.symmetric(vertical: 4.0),
78+
child: Row(
79+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
80+
children: const <Widget>[
81+
Text('Headphone'),
82+
Text('Connected'),
83+
],
84+
),
85+
),
86+
child: Row(
87+
mainAxisAlignment: MainAxisAlignment.end,
88+
children: const <Widget>[
89+
Text('On'),
90+
SizedBox(width: 5),
91+
Icon(CupertinoIcons.forward)
92+
],
93+
),
94+
),
95+
const CupertinoFormRow(
96+
prefix: PrefixWidget(
97+
icon: CupertinoIcons.bluetooth,
98+
title: 'Mobile Data',
99+
color: CupertinoColors.systemGreen,
100+
),
101+
child: Icon(CupertinoIcons.forward),
102+
),
103+
],
104+
),
105+
);
106+
}
107+
}
108+
109+
class PrefixWidget extends StatelessWidget {
110+
const PrefixWidget({
111+
Key? key,
112+
required this.icon,
113+
required this.title,
114+
required this.color,
115+
}) : super(key: key);
116+
117+
final IconData icon;
118+
final String title;
119+
final Color color;
120+
121+
@override
122+
Widget build(BuildContext context) {
123+
return Row(
124+
children: <Widget>[
125+
Container(
126+
padding: const EdgeInsets.all(4.0),
127+
decoration: BoxDecoration(
128+
color: color,
129+
borderRadius: BorderRadius.circular(4.0),
130+
),
131+
child: Icon(icon, color: CupertinoColors.white),
132+
),
133+
const SizedBox(width: 15),
134+
Text(title)
135+
],
136+
);
137+
}
138+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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/cupertino.dart';
6+
import 'package:flutter_api_samples/cupertino/form_row/cupertino_form_row.0.dart' as example;
7+
import 'package:flutter_test/flutter_test.dart';
8+
9+
void main() {
10+
testWidgets('Cupertino form section displays cupertino form rows', (WidgetTester tester) async {
11+
await tester.pumpWidget(
12+
const example.CupertinoFormRowApp(),
13+
);
14+
15+
expect(find.byType(CupertinoFormSection), findsOneWidget);
16+
expect(find.byType(CupertinoFormRow), findsNWidgets(4));
17+
expect(find.widgetWithText(CupertinoFormSection, 'Connectivity'), findsOneWidget);
18+
expect(find.widgetWithText(CupertinoFormRow, 'Airplane Mode'), findsOneWidget);
19+
expect(find.widgetWithText(CupertinoFormRow, 'Wi-Fi'), findsOneWidget);
20+
expect(find.widgetWithText(CupertinoFormRow, 'Bluetooth'), findsOneWidget);
21+
expect(find.widgetWithText(CupertinoFormRow, 'Mobile Data'), findsOneWidget);
22+
});
23+
}

packages/flutter/lib/src/cupertino/form_row.dart

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -34,50 +34,13 @@ const EdgeInsetsGeometry _kDefaultPadding =
3434
/// be shown in [CupertinoColors.destructiveRed] coloring and
3535
/// medium-weighted font.
3636
///
37-
/// {@tool snippet}
37+
/// {@tool dartpad}
38+
/// Creates a [CupertinoFormSection] containing a [CupertinoFormRow] with [prefix],
39+
/// [child], [helper] and [error] specified.
3840
///
39-
/// Creates a [CupertinoFormSection] containing a [CupertinoFormRow] with the
40-
/// [prefix], [child], [helper] and [error] widgets.
41-
///
42-
/// ```dart
43-
/// class FlutterDemo extends StatefulWidget {
44-
/// const FlutterDemo({Key? key}) : super(key: key);
45-
///
46-
/// @override
47-
/// State<FlutterDemo> createState() => _FlutterDemoState();
48-
/// }
49-
///
50-
/// class _FlutterDemoState extends State<FlutterDemo> {
51-
/// bool toggleValue = false;
52-
///
53-
/// @override
54-
/// Widget build(BuildContext context) {
55-
/// return CupertinoPageScaffold(
56-
/// child: Center(
57-
/// child: CupertinoFormSection(
58-
/// header: const Text('SECTION 1'),
59-
/// children: <Widget>[
60-
/// CupertinoFormRow(
61-
/// prefix: const Text('Toggle'),
62-
/// helper: const Text('Use your instincts'),
63-
/// error: toggleValue ? const Text('Cannot be true') : null,
64-
/// child: CupertinoSwitch(
65-
/// value: toggleValue,
66-
/// onChanged: (bool value) {
67-
/// setState(() {
68-
/// toggleValue = value;
69-
/// });
70-
/// },
71-
/// ),
72-
/// ),
73-
/// ],
74-
/// ),
75-
/// ),
76-
/// );
77-
/// }
78-
/// }
79-
/// ```
41+
/// ** See code in examples/api/lib/cupertino/form_row/cupertino_form_row.0.dart **
8042
/// {@end-tool}
43+
///
8144
class CupertinoFormRow extends StatelessWidget {
8245
/// Creates an iOS-style split form row with a standard prefix and child widget.
8346
/// Also provides a space for error and helper widgets that appear underneath.

0 commit comments

Comments
 (0)