Default multitouch scrolling ??
Mehran Khani
Application Developer | Swift & Flutter | Native iOS & Cross-Platform Development
Did you know? ??
There have been some pretty cool changes in the latest update (3.19) for Flutter. In my opinion, one of the most important ones is the "Default multitouch scrolling".
In this version, the flutter community made a change in “ScrollBehavior”( which is used by the?“ScrollConfiguration”?class to configure how scrollable widgets should behave OR as the documentation of scroll_configuration.dart?describes “How [Scrollable] widgets that are descendants of [child] should behave.”) and how the scrollable widgets work.?
In previous versions, the scrolling speed would be multiplied when users scrolled with two or multiple fingers. However, in version 3.19, this feature has been deactivated by default since it didn't meet the needs of many users and developers. Therefore, if you need that multitouch scrolling feature back, you can easily change the default behavior of your scrollable widgets such as "ListView", "GridView" and "SingleChildScrollView" by changing the value of the "multitouchDragStrategy" enum, which is a property of the "ScrollBehavior" class, to ".sumAllPointers" (which is initially set to ".latestPointer").
First, let's review some features of this change in how scrollable widgets should behave:
1. The recent change has made the scroll behavior more flexible, allowing it to match the users' needs.
2. You can easily extend the "MaterialScrollBehavior" class to create your own custom ScrollBehavior.
3. Easily controlling the user interface and adjusting different behaviors in different parts of the widget tree.
4. Improving performance and optimizing the functionality of scrollable widgets.
Now, let’s review how we can easily customize the behavior:
1. The best and easiest approach for defining your custom behavior is to call the ".copyWith" method of the "ScrollBehavior" class and modify/change the default "ScrollBehavior" as shown below:
领英推荐
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late ScrollController controller;
@override
void initState() {
super.initState();
controller = ScrollController();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
/*=================================================================
*** Wrap your scrollable widget with ScrollConfiguration ***
then in the "behavior:" property you can modify ScrollBehavior by calling the ".copyWith"
Make sure to set a different multitouchDragStrategy
to meet the requirements of your scrollable widget
other than that you can modify other behaviors such as " scrollbars:", "physics:" and "overscroll:"
=================================================================*/
body: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(
multitouchDragStrategy: MultitouchDragStrategy.sumAllPointers,
),
child: ListView.builder(
itemCount: 100,
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item ${index + 1}');
},
),
),
);
}
}
2. Other than that you can easily customize the behavior by extending "ScrollBehavior", "MaterialScrollBehavior" or "CupertinoScrollBehavior"; Then, simply pass it to "scrollBehavior:" in MaterialApp to customize the "ScrollBehavior" for your entire app. Let's take a look:
/*=================================================================
IN this approach, you simply create a class that extends either ScrollBehavior,
MaterialScrollBehavior, or CupertinoScrollBehavior.
In this class, you define a getter that overrides ScrollBehavior.multitouchDragStrategy. Additionally, you have the ability to modify and override other behavioral methods.
then just by setting your custom ScrollBehavior to MaterialApp.scrollBehavior you
will have all customized scroll behaviors in your app =================================================================*/
class CustomScrollBehavior extends ScrollBehavior {
@override
MultitouchDragStrategy get multitouchDragStrategy => MultitouchDragStrategy.sumAllPointers;
// remember here you can modify other scroll behaviors other than overriding MultitouchDragStrategy
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
scrollBehavior: CustomScrollBehavior(),
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Multitouch scrolling'),
);
}
}
Another similar approach is to first write a class that extends "MaterialScrollBehavior". Then, wrap your scrollable widget, which you want to describe its behavior, with "ScrollConfiguration" and pass the class as the value to the "behavior" property.
/*=================================================================
Similar to the previous approach, you follow all the steps, but instead of setting
scrollBehavior in your MaterialApp/CupertinoApp,
you just set the scrollBehavior in a specific widget, as we will see soon.
=================================================================*/
class CustomScrollBehavior extends ScrollBehavior {
@override
MultitouchDragStrategy get multitouchDragStrategy =>
MultitouchDragStrategy.sumAllPointers;
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late ScrollController controller;
@override
void initState() {
super.initState();
controller = ScrollController();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
/*===============================
and here you wrap your desired widget with ScrollConfiguration
and set the behavior: by your custom ScrollBehavior
===================================*/
body: ScrollConfiguration(
behavior: CustomScrollBehavior(),
child: ListView.builder(
itemCount: 100,
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item ${index + 1}');
},
),
),
);
}
}
Keep in mind :
The default "MultitouchDragStrategy.latestPointer" is used for non-Apple platforms like Android and Fuchsia OS, while ".averageBoundaryPointers" is the default for Apple platforms.?
Let’s take a look at the documentation. The following code snippet illustrates how the MultitouchDragStrategy is determined:
MultitouchDragStrategy getMultitouchDragStrategy(BuildContext context) {
switch (getPlatform(context)) {
case TargetPlatform.macOS:
case TargetPlatform.iOS:
return MultitouchDragStrategy.averageBoundaryPointers;
case TargetPlatform.linux:
case TargetPlatform.windows:
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return MultitouchDragStrategy.latestPointer;
}
}
Feel free to ask your questions or share your opinion below??
Co-founder and COO - CPO @ Roboquark | Product Management
9 个月Very informative