Add footer to CupertinoFormSection and fix CupertinoFormSection margins. (#72046)
This commit is contained in:
parent
781c9bcb4d
commit
bff0ec470a
@ -10,7 +10,7 @@ import 'theme.dart';
|
||||
|
||||
// Content padding determined via SwiftUI's `Form` view in the iOS 14.2 SDK.
|
||||
const EdgeInsetsGeometry _kDefaultPadding =
|
||||
EdgeInsetsDirectional.fromSTEB(16.0, 6.0, 6.0, 6.0);
|
||||
EdgeInsetsDirectional.fromSTEB(20.0, 6.0, 6.0, 6.0);
|
||||
|
||||
/// An iOS-style form row.
|
||||
///
|
||||
@ -149,22 +149,7 @@ class CupertinoFormRow extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CupertinoThemeData themeData = CupertinoTheme.of(context);
|
||||
final TextStyle textStyle = themeData.textTheme.textStyle;
|
||||
|
||||
final List<Widget> rowChildren = <Widget>[
|
||||
if (prefix != null)
|
||||
DefaultTextStyle(
|
||||
style: textStyle,
|
||||
child: prefix!,
|
||||
),
|
||||
Flexible(
|
||||
child: Align(
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
];
|
||||
final TextStyle textStyle = CupertinoTheme.of(context).textTheme.textStyle;
|
||||
|
||||
return Padding(
|
||||
padding: padding ?? _kDefaultPadding,
|
||||
@ -172,7 +157,19 @@ class CupertinoFormRow extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: rowChildren,
|
||||
children: <Widget>[
|
||||
if (prefix != null)
|
||||
DefaultTextStyle(
|
||||
style: textStyle,
|
||||
child: prefix!,
|
||||
),
|
||||
Flexible(
|
||||
child: Align(
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (helper != null)
|
||||
Align(
|
||||
|
@ -9,12 +9,16 @@ import 'colors.dart';
|
||||
|
||||
// Standard header margin, determined from SwiftUI's Forms in iOS 14.2 SDK.
|
||||
const EdgeInsetsDirectional _kDefaultHeaderMargin =
|
||||
EdgeInsetsDirectional.fromSTEB(16.5, 16.0, 16.5, 10.0);
|
||||
EdgeInsetsDirectional.fromSTEB(20.0, 16.0, 20.0, 10.0);
|
||||
|
||||
// Standard footer margin, determined from SwiftUI's Forms in iOS 14.2 SDK.
|
||||
const EdgeInsetsDirectional _kDefaultFooterMargin =
|
||||
EdgeInsetsDirectional.fromSTEB(20.0, 0.0, 20.0, 10.0);
|
||||
|
||||
// Used for iOS "Inset Grouped" margin, determined from SwiftUI's Forms in
|
||||
// iOS 14.2 SDK.
|
||||
const EdgeInsetsDirectional _kDefaultInsetGroupedRowsMargin =
|
||||
EdgeInsetsDirectional.fromSTEB(16.5, 0.0, 16.5, 16.5);
|
||||
EdgeInsetsDirectional.fromSTEB(20.0, 0.0, 20.0, 10.0);
|
||||
|
||||
// Used for iOS "Inset Grouped" border radius, estimated from SwiftUI's Forms in
|
||||
// iOS 14.2 SDK.
|
||||
@ -39,6 +43,9 @@ enum _CupertinoFormSectionType { base, insetGrouped }
|
||||
/// The [header] parameter sets the form section header. The section header lies
|
||||
/// above the [children] rows, with margins that match the iOS style.
|
||||
///
|
||||
/// The [footer] parameter sets the form section footer. The section footer
|
||||
/// lies below the [children] rows.
|
||||
///
|
||||
/// The [children] parameter is required and sets the list of rows shown in
|
||||
/// the section. The [children] parameter takes a list, as opposed to a more
|
||||
/// efficient builder function that lazy builds, because forms are intended to
|
||||
@ -69,6 +76,9 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
/// The [header] parameter sets the form section header. The section header
|
||||
/// lies above the [children] rows, with margins that match the iOS style.
|
||||
///
|
||||
/// The [footer] parameter sets the form section footer. The section footer
|
||||
/// lies below the [children] rows.
|
||||
///
|
||||
/// The [children] parameter is required and sets the list of rows shown in
|
||||
/// the section. The [children] parameter takes a list, as opposed to a more
|
||||
/// efficient builder function that lazy builds, because forms are intended to
|
||||
@ -93,6 +103,7 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
Key? key,
|
||||
required this.children,
|
||||
this.header,
|
||||
this.footer,
|
||||
this.margin = EdgeInsets.zero,
|
||||
this.backgroundColor = CupertinoColors.systemGroupedBackground,
|
||||
this.decoration,
|
||||
@ -111,6 +122,9 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
/// The [header] parameter sets the form section header. The section header
|
||||
/// lies above the [children] rows, with margins that match the iOS style.
|
||||
///
|
||||
/// The [footer] parameter sets the form section footer. The section footer
|
||||
/// lies below the [children] rows.
|
||||
///
|
||||
/// The [children] parameter is required and sets the list of rows shown in
|
||||
/// the section. The [children] parameter takes a list, as opposed to a more
|
||||
/// efficient builder function that lazy builds, because forms are intended to
|
||||
@ -136,6 +150,7 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
Key? key,
|
||||
required this.children,
|
||||
this.header,
|
||||
this.footer,
|
||||
this.margin = _kDefaultInsetGroupedRowsMargin,
|
||||
this.backgroundColor = CupertinoColors.systemGroupedBackground,
|
||||
this.decoration,
|
||||
@ -150,6 +165,10 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
/// [children] rows.
|
||||
final Widget? header;
|
||||
|
||||
/// Sets the form section footer. The section footer lies below the
|
||||
/// [children] rows.
|
||||
final Widget? footer;
|
||||
|
||||
/// Margin around the content area of the section encapsulating [children].
|
||||
///
|
||||
/// Defaults to zero padding if constructed with standard
|
||||
@ -228,6 +247,16 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
childrenWithDividers.add(longDivider);
|
||||
}
|
||||
|
||||
final BorderRadius childrenGroupBorderRadius;
|
||||
switch (_type) {
|
||||
case _CupertinoFormSectionType.insetGrouped:
|
||||
childrenGroupBorderRadius = _kDefaultInsetGroupedBorderRadius;
|
||||
break;
|
||||
case _CupertinoFormSectionType.base:
|
||||
childrenGroupBorderRadius = BorderRadius.zero;
|
||||
break;
|
||||
}
|
||||
|
||||
// Refactored the decorate children group in one place to avoid repeating it
|
||||
// twice down bellow in the returned widget.
|
||||
final DecoratedBox decoratedChildrenGroup = DecoratedBox(
|
||||
@ -237,7 +266,7 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
decoration?.color ??
|
||||
CupertinoColors.secondarySystemGroupedBackground,
|
||||
context),
|
||||
borderRadius: _kDefaultInsetGroupedBorderRadius,
|
||||
borderRadius: childrenGroupBorderRadius,
|
||||
),
|
||||
child: Column(
|
||||
children: childrenWithDividers,
|
||||
@ -250,31 +279,43 @@ class CupertinoFormSection extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: header == null
|
||||
? null
|
||||
: DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13.5,
|
||||
color:
|
||||
CupertinoColors.secondaryLabel.resolveFrom(context),
|
||||
),
|
||||
child: Padding(
|
||||
padding: _kDefaultHeaderMargin,
|
||||
child: header!,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (header != null)
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13.0,
|
||||
color: CupertinoColors.secondaryLabel.resolveFrom(context),
|
||||
),
|
||||
child: Padding(
|
||||
padding: _kDefaultHeaderMargin,
|
||||
child: header!,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: margin,
|
||||
child: clipBehavior == Clip.none
|
||||
? decoratedChildrenGroup
|
||||
: ClipRRect(
|
||||
borderRadius: _kDefaultInsetGroupedBorderRadius,
|
||||
borderRadius: childrenGroupBorderRadius,
|
||||
clipBehavior: clipBehavior,
|
||||
child: decoratedChildrenGroup),
|
||||
),
|
||||
if (footer != null)
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13.0,
|
||||
color: CupertinoColors.secondaryLabel.resolveFrom(context),
|
||||
),
|
||||
child: Padding(
|
||||
padding: _kDefaultFooterMargin,
|
||||
child: footer!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -8,20 +8,33 @@ import 'package:flutter/rendering.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Shows header', (WidgetTester tester) async {
|
||||
const Widget header = Text('Enter Value');
|
||||
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoFormSection(
|
||||
header: header,
|
||||
header: const Text('Header'),
|
||||
children: <Widget>[CupertinoTextFormFieldRow()],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(header, tester.widget(find.byType(Text)));
|
||||
expect(find.text('Header'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Shows footer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoFormSection(
|
||||
footer: const Text('Footer'),
|
||||
children: <Widget>[CupertinoTextFormFieldRow()],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Footer'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Shows long dividers in edge-to-edge section part 1',
|
||||
|
Loading…
x
Reference in New Issue
Block a user