mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Flutter 3.29 beta (#2571)
This commit is contained in:
@@ -30,11 +30,13 @@ void setupWindow() {
|
||||
setWindowMinSize(const Size(windowWidth, windowHeight));
|
||||
setWindowMaxSize(const Size(windowWidth, windowHeight));
|
||||
getCurrentScreen().then((screen) {
|
||||
setWindowFrame(Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
));
|
||||
setWindowFrame(
|
||||
Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -43,10 +45,11 @@ final demos = [
|
||||
Demo(
|
||||
name: 'Sign in with HTTP',
|
||||
route: 'signin_http',
|
||||
builder: (context) => SignInHttpDemo(
|
||||
// This sample uses a mock HTTP client.
|
||||
httpClient: mockClient,
|
||||
),
|
||||
builder:
|
||||
(context) => SignInHttpDemo(
|
||||
// This sample uses a mock HTTP client.
|
||||
httpClient: mockClient,
|
||||
),
|
||||
),
|
||||
Demo(
|
||||
name: 'Autofill',
|
||||
@@ -88,9 +91,7 @@ class FormApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
title: 'Form Samples',
|
||||
theme: ThemeData(
|
||||
colorSchemeSeed: Colors.teal,
|
||||
),
|
||||
theme: ThemeData(colorSchemeSeed: Colors.teal),
|
||||
routerConfig: router,
|
||||
);
|
||||
}
|
||||
@@ -102,12 +103,8 @@ class HomePage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Form Samples'),
|
||||
),
|
||||
body: ListView(
|
||||
children: [...demos.map((d) => DemoTile(demo: d))],
|
||||
),
|
||||
appBar: AppBar(title: const Text('Form Samples')),
|
||||
body: ListView(children: [...demos.map((d) => DemoTile(demo: d))]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ class _AutofillDemoState extends State<AutofillDemo> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Autofill'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Autofill')),
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: Scrollbar(
|
||||
@@ -101,14 +99,7 @@ class _AutofillDemoState extends State<AutofillDemo> {
|
||||
),
|
||||
autofillHints: [AutofillHints.countryCode],
|
||||
),
|
||||
].expand(
|
||||
(widget) => [
|
||||
widget,
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
)
|
||||
],
|
||||
)
|
||||
].expand((widget) => [widget, const SizedBox(height: 24)]),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -24,9 +24,7 @@ class _FormWidgetsDemoState extends State<FormWidgetsDemo> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Form widgets'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Form widgets')),
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: Scrollbar(
|
||||
@@ -89,8 +87,9 @@ class _FormWidgetsDemoState extends State<FormWidgetsDemo> {
|
||||
),
|
||||
Text(
|
||||
intl.NumberFormat.currency(
|
||||
symbol: "\$", decimalDigits: 0)
|
||||
.format(maxValue),
|
||||
symbol: "\$",
|
||||
decimalDigits: 0,
|
||||
).format(maxValue),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Slider(
|
||||
@@ -118,16 +117,20 @@ class _FormWidgetsDemoState extends State<FormWidgetsDemo> {
|
||||
});
|
||||
},
|
||||
),
|
||||
Text('Brushed Teeth',
|
||||
style: Theme.of(context).textTheme.titleMedium),
|
||||
Text(
|
||||
'Brushed Teeth',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text('Enable feature',
|
||||
style: Theme.of(context).textTheme.bodyLarge),
|
||||
Text(
|
||||
'Enable feature',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Switch(
|
||||
value: enableFeature,
|
||||
onChanged: (enabled) {
|
||||
@@ -139,13 +142,8 @@ class _FormWidgetsDemoState extends State<FormWidgetsDemo> {
|
||||
],
|
||||
),
|
||||
].expand(
|
||||
(widget) => [
|
||||
widget,
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
)
|
||||
],
|
||||
)
|
||||
(widget) => [widget, const SizedBox(height: 24)],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -162,10 +160,7 @@ class _FormDatePicker extends StatefulWidget {
|
||||
final DateTime date;
|
||||
final ValueChanged<DateTime> onChanged;
|
||||
|
||||
const _FormDatePicker({
|
||||
required this.date,
|
||||
required this.onChanged,
|
||||
});
|
||||
const _FormDatePicker({required this.date, required this.onChanged});
|
||||
|
||||
@override
|
||||
State<_FormDatePicker> createState() => _FormDatePickerState();
|
||||
@@ -182,10 +177,7 @@ class _FormDatePickerState extends State<_FormDatePicker> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
'Date',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text('Date', style: Theme.of(context).textTheme.bodyLarge),
|
||||
Text(
|
||||
intl.DateFormat.yMd().format(widget.date),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
@@ -209,7 +201,7 @@ class _FormDatePickerState extends State<_FormDatePicker> {
|
||||
|
||||
widget.onChanged(newDate);
|
||||
},
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ final http.Client mockClient = MockClient(_mockHandler);
|
||||
|
||||
Future<http.Response> _mockHandler(http.Request request) async {
|
||||
var decodedJson = Map<String, dynamic>.from(
|
||||
json.decode(request.body) as Map<String, dynamic>);
|
||||
json.decode(request.body) as Map<String, dynamic>,
|
||||
);
|
||||
|
||||
if (decodedJson['email'] == 'root' && decodedJson['password'] == 'password') {
|
||||
return http.Response('', 200);
|
||||
|
||||
@@ -15,10 +15,7 @@ class FormData {
|
||||
String? email;
|
||||
String? password;
|
||||
|
||||
FormData({
|
||||
this.email,
|
||||
this.password,
|
||||
});
|
||||
FormData({this.email, this.password});
|
||||
|
||||
factory FormData.fromJson(Map<String, dynamic> json) =>
|
||||
_$FormDataFromJson(json);
|
||||
@@ -29,10 +26,7 @@ class FormData {
|
||||
class SignInHttpDemo extends StatefulWidget {
|
||||
final http.Client? httpClient;
|
||||
|
||||
const SignInHttpDemo({
|
||||
this.httpClient,
|
||||
super.key,
|
||||
});
|
||||
const SignInHttpDemo({this.httpClient, super.key});
|
||||
|
||||
@override
|
||||
State<SignInHttpDemo> createState() => _SignInHttpDemoState();
|
||||
@@ -44,9 +38,7 @@ class _SignInHttpDemoState extends State<SignInHttpDemo> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Sign in Form'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Sign in Form')),
|
||||
body: Form(
|
||||
child: Scrollbar(
|
||||
child: SingleChildScrollView(
|
||||
@@ -81,25 +73,19 @@ class _SignInHttpDemoState extends State<SignInHttpDemo> {
|
||||
onPressed: () async {
|
||||
// Use a JSON encoded string to send
|
||||
var result = await widget.httpClient!.post(
|
||||
Uri.parse('https://example.com/signin'),
|
||||
body: json.encode(formData.toJson()),
|
||||
headers: {'content-type': 'application/json'});
|
||||
Uri.parse('https://example.com/signin'),
|
||||
body: json.encode(formData.toJson()),
|
||||
headers: {'content-type': 'application/json'},
|
||||
);
|
||||
|
||||
_showDialog(switch (result.statusCode) {
|
||||
200 => 'Successfully signed in.',
|
||||
401 => 'Unable to sign in.',
|
||||
_ => 'Something went wrong. Please try again.'
|
||||
_ => 'Something went wrong. Please try again.',
|
||||
});
|
||||
},
|
||||
),
|
||||
].expand(
|
||||
(widget) => [
|
||||
widget,
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
)
|
||||
],
|
||||
)
|
||||
].expand((widget) => [widget, const SizedBox(height: 24)]),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -111,15 +97,16 @@ class _SignInHttpDemoState extends State<SignInHttpDemo> {
|
||||
void _showDialog(String message) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(message),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text(message),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ FormData _$FormDataFromJson(Map<String, dynamic> json) {
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$FormDataToJson(FormData instance) => <String, dynamic>{
|
||||
'email': instance.email,
|
||||
'password': instance.password,
|
||||
};
|
||||
'email': instance.email,
|
||||
'password': instance.password,
|
||||
};
|
||||
|
||||
@@ -38,18 +38,19 @@ class _FormValidationDemoState extends State<FormValidationDemo> {
|
||||
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Your story'),
|
||||
content: Text('The $adjective developer saw a $noun'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Done'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: const Text('Your story'),
|
||||
content: Text('The $adjective developer saw a $noun'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Done'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -85,9 +86,7 @@ class _FormValidationDemoState extends State<FormValidationDemo> {
|
||||
adjective = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// A text field that validates that the text is a noun.
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
@@ -108,9 +107,7 @@ class _FormValidationDemoState extends State<FormValidationDemo> {
|
||||
noun = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// A custom form field that requires the user to check a
|
||||
// checkbox.
|
||||
FormField<bool>(
|
||||
@@ -148,11 +145,11 @@ class _FormValidationDemoState extends State<FormValidationDemo> {
|
||||
if (!formFieldState.isValid)
|
||||
Text(
|
||||
formFieldState.errorText ?? "",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(
|
||||
color: Theme.of(context).colorScheme.error),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall!.copyWith(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ publish_to: "none"
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
sdk: ^3.7.0-0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
||||
@@ -23,11 +23,9 @@ void main() {
|
||||
}
|
||||
|
||||
Future<void> _signIn(WidgetTester tester, String email, String password) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: SignInHttpDemo(
|
||||
httpClient: mockClient,
|
||||
),
|
||||
));
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(home: SignInHttpDemo(httpClient: mockClient)),
|
||||
);
|
||||
|
||||
var textFormField = find.byType(TextFormField);
|
||||
expect(textFormField, findsNWidgets(2));
|
||||
|
||||
Reference in New Issue
Block a user