This tutorial shows you how to use the SelectionArea
widget in Flutter.
SelectionArea
is a widget that creates an area that allows user selections. It can be useful if you want to make the widgets of a subtree selectable by the users. In addition to providing the selection capability, it also allows the application developers to customize the selection control and appearance. Below I'm going to explain how to use it and what you can do with the widget.
Using SelectionArea
The constructor of the widget can be seen below.
const SelectionArea({
Key? key,
FocusNode? focusNode,
TextSelectionControls? selectionControls,
Widget Function(BuildContext, SelectableRegionState)? contextMenuBuilder = _defaultContextMenuBuilder,
TextMagnifierConfiguration? magnifierConfiguration,
void Function(SelectedContent?)? onSelectionChanged,
required Widget child,
});
For the basic usage, you are only required to pass the child
argument which is the widget whose content is selectable. You can pass any widget for it.
SelectionArea(
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Woolha'),
Text('dot'),
Text('com'),
],
),
// other arguments
)
Set Selection Controls
By default, when the selection is not empty, Flutter will show a selection control toolbar with several actions such as copy. The toolbar displayed by default depends on the platform where the Flutter application runs. For example, Flutter will show a Cupertino-styled one on iOS. On Android, it will use Material-styled. If you want to override the default toolbar, you can set it explicitly by passing a TextSelectionControls
object as the selectionControls
argument.
SelectionArea(
selectionControls: CupertinoTextSelectionControls(),
// other arguments
)
Set Context Menu Builder
If you need to have a custom toolbar with different actions, you can pass a function that returns a widget as the contextMenuBuilder
argument. The function needs to have two parameters. The first one is the BuildContext
, while the other is SelectableRegionState
.
Unless you need to have a completely different layout, you can use AdaptiveTextSelectionToolbar.buttonItems
to build the widget. It requires you to create several ContextMenuButtonItem
widgets where you can define the type and action of each button item.
SelectionArea(
contextMenuBuilder: (
BuildContext context,
SelectableRegionState selectableRegionState,
) {
return AdaptiveTextSelectionToolbar.buttonItems(
buttonItems: <ContextMenuButtonItem>[
ContextMenuButtonItem(
onPressed: () {
selectableRegionState
.copySelection(SelectionChangedCause.toolbar);
},
type: ContextMenuButtonType.copy,
),
ContextMenuButtonItem(
onPressed: () {
selectableRegionState.selectAll(SelectionChangedCause.toolbar);
},
type: ContextMenuButtonType.selectAll,
),
ContextMenuButtonItem(
onPressed: () {
// Other action
},
type: ContextMenuButtonType.custom,
label: 'Like',
),
],
anchors: selectableRegionState.contextMenuAnchors,
);
},
// other arguments
)
Handle Selection Changes
Every time the user changes the selection, you can get the latest selected text by passing a function as the onSelectionChanged
argument. The passed function must have a parameter whose type is SelectedContent
. You can get the value by accessing its plainText
property.
SelectionArea
Parameters
Key? key
: The widget's key, used to control how a widget is replaced with another.FocusNode? focusNode
: Focus node of the widget.TextSelectionControls? selectionControls
: The delegate to build the selection handles and toolbar.Widget Function(BuildContext, SelectableRegionState)? contextMenuBuilder = _defaultContextMenuBuilder
: Function to return a text selection toolbar widget when requested by the user.TextMagnifierConfiguration? magnifierConfiguration
: Configuration for magnifier.void Function(SelectedContent?)? onSelectionChanged
: Function to be called when the selection changes.required Widget child
: The widget where the selection area is applied to.
Full Code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Woolha.com Flutter Tutorial',
home: MyPage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyPage extends StatefulWidget {
const MyPage({super.key});
@override
State<StatefulWidget> createState() {
return MyPageState();
}
}
class MyPageState extends State<MyPage> {
String? _selectedContent;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SelectionArea(
selectionControls: CupertinoTextSelectionControls(),
contextMenuBuilder: (
BuildContext context,
SelectableRegionState selectableRegionState,
) {
return AdaptiveTextSelectionToolbar.buttonItems(
buttonItems: <ContextMenuButtonItem>[
ContextMenuButtonItem(
onPressed: () {
selectableRegionState
.copySelection(SelectionChangedCause.toolbar);
},
type: ContextMenuButtonType.copy,
),
ContextMenuButtonItem(
onPressed: () {
selectableRegionState.selectAll(SelectionChangedCause.toolbar);
},
type: ContextMenuButtonType.selectAll,
),
ContextMenuButtonItem(
onPressed: () {
// Other action
},
type: ContextMenuButtonType.custom,
label: 'Like',
),
],
anchors: selectableRegionState.contextMenuAnchors,
);
},
onSelectionChanged: (SelectedContent? selectedContent) {
print('Selected content: ${selectedContent?.plainText}');
setState(() {
_selectedContent = selectedContent?.plainText;
});
},
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Woolha'),
Text('dot'),
Text('com'),
],
),
),
const SizedBox(height: 50),
Text('Selected content: ${_selectedContent ?? '-'}')
],
),
),
);
}
}
Summary
Flutter's SelectionArea
widget can be used if you want to allow the users to perform text selections on a widget subtree. With this widget, you don't have to make each widget selectable such as by using the SelectableText
. Just put the SelectionArea
widget as the ancestor of all selectable widgets.