Add Material 3 RadioListTile
example and update existing examples (#119716)
* Add Material 3 `RadioListTile` example and update existing examples * Update examples with `useMaterial3: true` and update example descriptions. * add a `ColorScheme` colour
This commit is contained in:
parent
c5e8757fcb
commit
7177c413a9
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flutter code sample for custom labeled radio.
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
void main() => runApp(const LabeledRadioApp());
|
||||||
|
|
||||||
|
class LabeledRadioApp extends StatelessWidget {
|
||||||
|
const LabeledRadioApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(useMaterial3: true),
|
||||||
|
home: Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Custom Labeled Radio Sample')),
|
||||||
|
body: const LabeledRadioExample(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinkedLabelRadio extends StatelessWidget {
|
||||||
|
const LinkedLabelRadio({
|
||||||
|
super.key,
|
||||||
|
required this.label,
|
||||||
|
required this.padding,
|
||||||
|
required this.groupValue,
|
||||||
|
required this.value,
|
||||||
|
required this.onChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String label;
|
||||||
|
final EdgeInsets padding;
|
||||||
|
final bool groupValue;
|
||||||
|
final bool value;
|
||||||
|
final ValueChanged<bool> onChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: padding,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Radio<bool>(
|
||||||
|
groupValue: groupValue,
|
||||||
|
value: value,
|
||||||
|
onChanged: (bool? newValue) {
|
||||||
|
onChanged(newValue!);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: label,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
debugPrint('Label has been tapped.');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LabeledRadioExample extends StatefulWidget {
|
||||||
|
const LabeledRadioExample({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LabeledRadioExample> createState() => _LabeledRadioExampleState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LabeledRadioExampleState extends State<LabeledRadioExample> {
|
||||||
|
bool _isRadioSelected = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
LinkedLabelRadio(
|
||||||
|
label: 'First tappable label text',
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
value: true,
|
||||||
|
groupValue: _isRadioSelected,
|
||||||
|
onChanged: (bool newValue) {
|
||||||
|
setState(() {
|
||||||
|
_isRadioSelected = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
LinkedLabelRadio(
|
||||||
|
label: 'Second tappable label text',
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
value: false,
|
||||||
|
groupValue: _isRadioSelected,
|
||||||
|
onChanged: (bool newValue) {
|
||||||
|
setState(() {
|
||||||
|
_isRadioSelected = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -2,24 +2,22 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// Flutter code sample for [RadioListTile].
|
// Flutter code sample for custom labeled radio.
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() => runApp(const MyApp());
|
void main() => runApp(const LabeledRadioApp());
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class LabeledRadioApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const LabeledRadioApp({super.key});
|
||||||
|
|
||||||
static const String _title = 'Flutter Code Sample';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: _title,
|
theme: ThemeData(useMaterial3: true),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text(_title)),
|
appBar: AppBar(title: const Text('Custom Labeled Radio Sample')),
|
||||||
body: const MyStatefulWidget(),
|
body: const LabeledRadioExample(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -68,14 +66,14 @@ class LabeledRadio extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyStatefulWidget extends StatefulWidget {
|
class LabeledRadioExample extends StatefulWidget {
|
||||||
const MyStatefulWidget({super.key});
|
const LabeledRadioExample({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
|
State<LabeledRadioExample> createState() => _LabeledRadioExampleState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
class _LabeledRadioExampleState extends State<LabeledRadioExample> {
|
||||||
bool _isRadioSelected = false;
|
bool _isRadioSelected = false;
|
||||||
|
|
||||||
@override
|
@override
|
@ -6,20 +6,18 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() => runApp(const MyApp());
|
void main() => runApp(const RadioListTileApp());
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class RadioListTileApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const RadioListTileApp({super.key});
|
||||||
|
|
||||||
static const String _title = 'Flutter Code Sample';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: _title,
|
theme: ThemeData(useMaterial3: true),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text(_title)),
|
appBar: AppBar(title: const Text('RadioListTile Sample')),
|
||||||
body: const MyStatefulWidget(),
|
body: const RadioListTileExample(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -27,14 +25,14 @@ class MyApp extends StatelessWidget {
|
|||||||
|
|
||||||
enum SingingCharacter { lafayette, jefferson }
|
enum SingingCharacter { lafayette, jefferson }
|
||||||
|
|
||||||
class MyStatefulWidget extends StatefulWidget {
|
class RadioListTileExample extends StatefulWidget {
|
||||||
const MyStatefulWidget({super.key});
|
const RadioListTileExample({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
|
State<RadioListTileExample> createState() => _RadioListTileExampleState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
class _RadioListTileExampleState extends State<RadioListTileExample> {
|
||||||
SingingCharacter? _character = SingingCharacter.lafayette;
|
SingingCharacter? _character = SingingCharacter.lafayette;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -4,113 +4,73 @@
|
|||||||
|
|
||||||
// Flutter code sample for [RadioListTile].
|
// Flutter code sample for [RadioListTile].
|
||||||
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() => runApp(const MyApp());
|
void main() => runApp(const RadioListTileApp());
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class RadioListTileApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const RadioListTileApp({super.key});
|
||||||
|
|
||||||
static const String _title = 'Flutter Code Sample';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: _title,
|
theme: ThemeData(useMaterial3: true),
|
||||||
home: Scaffold(
|
home: const RadioListTileExample(),
|
||||||
appBar: AppBar(title: const Text(_title)),
|
|
||||||
body: const MyStatefulWidget(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkedLabelRadio extends StatelessWidget {
|
enum Groceries { pickles, tomato, lettuce }
|
||||||
const LinkedLabelRadio({
|
|
||||||
super.key,
|
|
||||||
required this.label,
|
|
||||||
required this.padding,
|
|
||||||
required this.groupValue,
|
|
||||||
required this.value,
|
|
||||||
required this.onChanged,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String label;
|
class RadioListTileExample extends StatefulWidget {
|
||||||
final EdgeInsets padding;
|
const RadioListTileExample({super.key});
|
||||||
final bool groupValue;
|
|
||||||
final bool value;
|
|
||||||
final ValueChanged<bool> onChanged;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<RadioListTileExample> createState() => _RadioListTileExampleState();
|
||||||
return Padding(
|
|
||||||
padding: padding,
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Radio<bool>(
|
|
||||||
groupValue: groupValue,
|
|
||||||
value: value,
|
|
||||||
onChanged: (bool? newValue) {
|
|
||||||
onChanged(newValue!);
|
|
||||||
}),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
text: label,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.blueAccent,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = () {
|
|
||||||
debugPrint('Label has been tapped.');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyStatefulWidget extends StatefulWidget {
|
class _RadioListTileExampleState extends State<RadioListTileExample> {
|
||||||
const MyStatefulWidget({super.key});
|
Groceries? _groceryItem = Groceries.pickles;
|
||||||
|
|
||||||
@override
|
|
||||||
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
|
||||||
bool _isRadioSelected = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('RadioListTile Sample')),
|
||||||
body: Column(
|
body: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
LinkedLabelRadio(
|
RadioListTile<Groceries>(
|
||||||
label: 'First tappable label text',
|
value: Groceries.pickles,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
groupValue: _groceryItem,
|
||||||
value: true,
|
onChanged: (Groceries? value) {
|
||||||
groupValue: _isRadioSelected,
|
|
||||||
onChanged: (bool newValue) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isRadioSelected = newValue;
|
_groceryItem = value;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
title: const Text('Pickles'),
|
||||||
|
subtitle: const Text('Supporting text'),
|
||||||
),
|
),
|
||||||
LinkedLabelRadio(
|
RadioListTile<Groceries>(
|
||||||
label: 'Second tappable label text',
|
value: Groceries.tomato,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
groupValue: _groceryItem,
|
||||||
value: false,
|
onChanged: (Groceries? value) {
|
||||||
groupValue: _isRadioSelected,
|
|
||||||
onChanged: (bool newValue) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isRadioSelected = newValue;
|
_groceryItem = value;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
title: const Text('Tomato'),
|
||||||
|
subtitle: const Text('Longer supporting text to demonstrate how the text wraps and the radio is centered vertically with the text.'),
|
||||||
|
),
|
||||||
|
RadioListTile<Groceries>(
|
||||||
|
value: Groceries.lettuce,
|
||||||
|
groupValue: _groceryItem,
|
||||||
|
onChanged: (Groceries? value) {
|
||||||
|
setState(() {
|
||||||
|
_groceryItem = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
title: const Text('Lettuce'),
|
||||||
|
subtitle: const Text("Longer supporting text to demonstrate how the text wraps and how setting 'RadioListTile.isThreeLine = true' aligns the radio to the top vertically with the text."),
|
||||||
|
isThreeLine: true,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -6,33 +6,31 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() => runApp(const MyApp());
|
void main() => runApp(const RadioListTileApp());
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class RadioListTileApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const RadioListTileApp({super.key});
|
||||||
|
|
||||||
static const String _title = 'Flutter Code Sample';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: _title,
|
theme: ThemeData(useMaterial3: true),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text(_title)),
|
appBar: AppBar(title: const Text('RadioListTile.toggleable Sample')),
|
||||||
body: const MyStatefulWidget(),
|
body: const RadioListTileExample(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyStatefulWidget extends StatefulWidget {
|
class RadioListTileExample extends StatefulWidget {
|
||||||
const MyStatefulWidget({super.key});
|
const RadioListTileExample({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
|
State<RadioListTileExample> createState() => _RadioListTileExampleState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
class _RadioListTileExampleState extends State<RadioListTileExample> {
|
||||||
int? groupValue;
|
int? groupValue;
|
||||||
static const List<String> selections = <String>[
|
static const List<String> selections = <String>[
|
||||||
'Hercules Mulligan',
|
'Hercules Mulligan',
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_api_samples/material/radio_list_tile/custom_labeled_radio.0.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('LinkedLabelRadio contains RichText and Radio', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.LabeledRadioApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Label text is in a RichText widget with the correct text.
|
||||||
|
final RichText richText = tester.widget(find.byType(RichText).first);
|
||||||
|
expect(richText.text.toPlainText(), 'First tappable label text');
|
||||||
|
|
||||||
|
// First Radio is initially unchecked.
|
||||||
|
Radio<bool> radio = tester.widget(find.byType(Radio<bool>).first);
|
||||||
|
expect(radio.value, true);
|
||||||
|
expect(radio.groupValue, false);
|
||||||
|
|
||||||
|
// Last Radio is initially checked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).last);
|
||||||
|
expect(radio.value, false);
|
||||||
|
expect(radio.groupValue, false);
|
||||||
|
|
||||||
|
// Tap the first radio.
|
||||||
|
await tester.tap(find.byType(Radio<bool>).first);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// First Radio is now checked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).first);
|
||||||
|
expect(radio.value, true);
|
||||||
|
expect(radio.groupValue, true);
|
||||||
|
|
||||||
|
// Last Radio is now unchecked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).last);
|
||||||
|
expect(radio.value, false);
|
||||||
|
expect(radio.groupValue, true);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_api_samples/material/radio_list_tile/custom_labeled_radio.1.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Tapping LabeledRadio toggles the radio', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.LabeledRadioApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// First Radio is initially unchecked.
|
||||||
|
Radio<bool> radio = tester.widget(find.byType(Radio<bool>).first);
|
||||||
|
expect(radio.value, true);
|
||||||
|
expect(radio.groupValue, false);
|
||||||
|
|
||||||
|
// Last Radio is initially checked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).last);
|
||||||
|
expect(radio.value, false);
|
||||||
|
expect(radio.groupValue, false);
|
||||||
|
|
||||||
|
// Tap the first labeled radio to toggle the Radio widget.
|
||||||
|
await tester.tap(find.byType(example.LabeledRadio).first);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// First Radio is now checked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).first);
|
||||||
|
expect(radio.value, true);
|
||||||
|
expect(radio.groupValue, true);
|
||||||
|
|
||||||
|
// Last Radio is now unchecked.
|
||||||
|
radio = tester.widget(find.byType(Radio<bool>).last);
|
||||||
|
expect(radio.value, false);
|
||||||
|
expect(radio.groupValue, true);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_api_samples/material/radio_list_tile/radio_list_tile.0.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Can update RadioListTile group value', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.RadioListTileApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the number of RadioListTiles.
|
||||||
|
expect(find.byType(RadioListTile<example.SingingCharacter>), findsNWidgets(2));
|
||||||
|
|
||||||
|
// The initial group value is lafayette for the first RadioListTile.
|
||||||
|
RadioListTile<example.SingingCharacter> radioListTile = tester.widget(find.byType(RadioListTile<example.SingingCharacter>).first);
|
||||||
|
expect(radioListTile.groupValue, example.SingingCharacter.lafayette);
|
||||||
|
|
||||||
|
// The initial group value is lafayette for the last RadioListTile.
|
||||||
|
radioListTile = tester.widget(find.byType(RadioListTile<example.SingingCharacter>).last);
|
||||||
|
expect(radioListTile.groupValue, example.SingingCharacter.lafayette);
|
||||||
|
|
||||||
|
// Tap the last RadioListTile to change the group value to jefferson.
|
||||||
|
await tester.tap(find.byType(RadioListTile<example.SingingCharacter>).last);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// The group value is now jefferson for the first RadioListTile.
|
||||||
|
radioListTile = tester.widget(find.byType(RadioListTile<example.SingingCharacter>).first);
|
||||||
|
expect(radioListTile.groupValue, example.SingingCharacter.jefferson);
|
||||||
|
|
||||||
|
// The group value is now jefferson for the last RadioListTile.
|
||||||
|
radioListTile = tester.widget(find.byType(RadioListTile<example.SingingCharacter>).last);
|
||||||
|
expect(radioListTile.groupValue, example.SingingCharacter.jefferson);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_api_samples/material/radio_list_tile/radio_list_tile.1.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Radio aligns appropriately', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.RadioListTileApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(RadioListTile<example.Groceries>), findsNWidgets(3));
|
||||||
|
|
||||||
|
Offset tileTopLeft = tester.getTopLeft(find.byType(RadioListTile<example.Groceries>).at(0));
|
||||||
|
Offset radioTopLeft = tester.getTopLeft(find.byType(Radio<example.Groceries>).at(0));
|
||||||
|
|
||||||
|
// The radio is centered vertically with the text.
|
||||||
|
expect(radioTopLeft - tileTopLeft, const Offset(16.0, 16.0));
|
||||||
|
|
||||||
|
tileTopLeft = tester.getTopLeft(find.byType(RadioListTile<example.Groceries>).at(1));
|
||||||
|
radioTopLeft = tester.getTopLeft(find.byType(Radio<example.Groceries>).at(1));
|
||||||
|
|
||||||
|
// The radio is centered vertically with the text.
|
||||||
|
expect(radioTopLeft - tileTopLeft, const Offset(16.0, 30.0));
|
||||||
|
|
||||||
|
tileTopLeft = tester.getTopLeft(find.byType(RadioListTile<example.Groceries>).at(2));
|
||||||
|
radioTopLeft = tester.getTopLeft(find.byType(Radio<example.Groceries>).at(2));
|
||||||
|
|
||||||
|
// The radio is aligned to the top vertically with the text.
|
||||||
|
expect(radioTopLeft - tileTopLeft, const Offset(16.0, 8.0));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Radios can be checked', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.RadioListTileApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(RadioListTile<example.Groceries>), findsNWidgets(3));
|
||||||
|
final Finder radioListTile = find.byType(RadioListTile<example.Groceries>);
|
||||||
|
|
||||||
|
// Initially the first radio is checked.
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(0)).groupValue,
|
||||||
|
example.Groceries.pickles,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(1)).groupValue,
|
||||||
|
example.Groceries.pickles,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(2)).groupValue,
|
||||||
|
example.Groceries.pickles,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tap the second radio.
|
||||||
|
await tester.tap(find.byType(Radio<example.Groceries>).at(1));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The second radio is checked.
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(0)).groupValue,
|
||||||
|
example.Groceries.tomato,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(1)).groupValue,
|
||||||
|
example.Groceries.tomato,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(2)).groupValue,
|
||||||
|
example.Groceries.tomato,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tap the third radio.
|
||||||
|
await tester.tap(find.byType(Radio<example.Groceries>).at(2));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The third radio is checked.
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(0)).groupValue,
|
||||||
|
example.Groceries.lettuce,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(1)).groupValue,
|
||||||
|
example.Groceries.lettuce,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.widget<RadioListTile<example.Groceries>>(radioListTile.at(2)).groupValue,
|
||||||
|
example.Groceries.lettuce,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_api_samples/material/radio_list_tile/radio_list_tile.toggleable.0.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('RadioListTile is toggleable', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const example.RadioListTileApp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initially the third radio button is not selected.
|
||||||
|
Radio<int> radio = tester.widget(find.byType(Radio<int>).at(2));
|
||||||
|
expect(radio.value, 2);
|
||||||
|
expect(radio.groupValue, null);
|
||||||
|
|
||||||
|
// Tap the third radio button.
|
||||||
|
await tester.tap(find.text('Philip Schuyler'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The third radio button is now selected.
|
||||||
|
radio = tester.widget(find.byType(Radio<int>).at(2));
|
||||||
|
expect(radio.value, 2);
|
||||||
|
expect(radio.groupValue, 2);
|
||||||
|
|
||||||
|
// Tap the third radio button again.
|
||||||
|
await tester.tap(find.text('Philip Schuyler'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The third radio button is now unselected.
|
||||||
|
radio = tester.widget(find.byType(Radio<int>).at(2));
|
||||||
|
expect(radio.value, 2);
|
||||||
|
expect(radio.groupValue, null);
|
||||||
|
});
|
||||||
|
}
|
@ -86,6 +86,13 @@ import 'theme_data.dart';
|
|||||||
/// ** See code in examples/api/lib/material/radio_list_tile/radio_list_tile.0.dart **
|
/// ** See code in examples/api/lib/material/radio_list_tile/radio_list_tile.0.dart **
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
|
/// {@tool dartpad}
|
||||||
|
/// This sample demonstrates how [RadioListTile] positions the radio widget
|
||||||
|
/// relative to the text in different configurations.
|
||||||
|
///
|
||||||
|
/// ** See code in examples/api/lib/material/radio_list_tile/radio_list_tile.1.dart **
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
/// ## Semantics in RadioListTile
|
/// ## Semantics in RadioListTile
|
||||||
///
|
///
|
||||||
/// Since the entirety of the RadioListTile is interactive, it should represent
|
/// Since the entirety of the RadioListTile is interactive, it should represent
|
||||||
@ -110,7 +117,7 @@ import 'theme_data.dart';
|
|||||||
/// LinkedLabelRadio, that includes an interactive [RichText] widget that
|
/// LinkedLabelRadio, that includes an interactive [RichText] widget that
|
||||||
/// handles tap gestures.
|
/// handles tap gestures.
|
||||||
///
|
///
|
||||||
/// ** See code in examples/api/lib/material/radio_list_tile/radio_list_tile.1.dart **
|
/// ** See code in examples/api/lib/material/radio_list_tile/custom_labeled_radio.0.dart **
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
/// ## RadioListTile isn't exactly what I want
|
/// ## RadioListTile isn't exactly what I want
|
||||||
@ -126,7 +133,7 @@ import 'theme_data.dart';
|
|||||||
/// Here is an example of a custom LabeledRadio widget, but you can easily
|
/// Here is an example of a custom LabeledRadio widget, but you can easily
|
||||||
/// make your own configurable widget.
|
/// make your own configurable widget.
|
||||||
///
|
///
|
||||||
/// ** See code in examples/api/lib/material/radio_list_tile/radio_list_tile.2.dart **
|
/// ** See code in examples/api/lib/material/radio_list_tile/custom_labeled_radio.1.dart **
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user