'How do I implement correctly`HitTestBehavior.translucent`in a gesture detector?
given the code below
import 'package:flutter/material.dart';
Future<void> _showMyDialog(BuildContext context) async => showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Success'),
content: const Text('nice job!'),
actions: <Widget>[
TextButton(
child: const Text('done'),
onPressed: Navigator.of(context).pop,
),
],
),
);
void main() => runApp(
const MaterialApp(
home: SafeArea(
child: MyHomePage(),
),
),
);
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => Material(
child: Stack(
fit: StackFit.expand,
children: [
Positioned(
bottom: 25,
right: 25,
child: FloatingActionButton(
child: const Icon(Icons.message),
onPressed: () => _showMyDialog(context),
),
),
PageView.builder(
itemBuilder: (context, index) => Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width / 2,
child: const ColoredBox(
color: Color.fromRGBO(60, 30, 10, .5),
),
),
),
),
],
),
);
}
how do I make the button clickable without changing the order of the children in the stack and keeping the scroll view scrollable?
I have tried wrapping the PageView in a GestureDetector without results
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: null,
child: PageView.builder(
itemBuilder: (context, index) => ...
),
),
Solution 1:[1]
Updated Answer
The problem is PageView takes up the whole screen.
There is no visible part of FloatingActionButton regarding gesture events.
If you don't want to change the order of your stack children's widgets, you have to change the PageView area.
Below is the updated code snippet.
The PageView is scrollable but only in its area. The FloatingActionButton is clickable.
import 'package:flutter/material.dart';
Future<void> _showMyDialog(BuildContext context) async => showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Success'),
content: const Text('nice job!'),
actions: <Widget>[
TextButton(
child: const Text('done'),
onPressed: Navigator.of(context).pop,
),
],
),
);
void main() => runApp(
const MaterialApp(
home: SafeArea(
child: MyHomePage(),
),
),
);
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => Material(
child: Stack(
children: [
Positioned(
bottom: 25,
right: 25,
child: FloatingActionButton(
child: const Icon(Icons.message),
onPressed: () => _showMyDialog(context),
),
),
Positioned( //// <------
//// The page ends before it can cover the floating action button.
/// But if the screen size changes, you might have to see how to make it work.
left: MediaQuery.of(context).size.width / 4,
top: 0,
bottom: 0,
width: MediaQuery.of(context).size.width / 2,
child: PageView.builder(
itemCount: 3,
itemBuilder: (context, index) => ColoredBox(
color: Color.fromRGBO(60, 30, index * 100, .5),
),
),
),
],
),
);
}
You can have a global PageView controller to set the scrollable functionality outside of the pageview area.
Old Answer
Wrap the PageView (the top widget which must be transparent to any tap) with IgnorePointer and set the ignoring field to true.
This will make the FloatingActionButton (the down widget) listen to tap events.
Here is the code snippet with change:
...
child: FloatingActionButton(
child: const Icon(Icons.message),
onPressed: () => _showMyDialog(context),
),
),
IgnorePointer( /// <---------- Wrap with IgnorePointer
ignoring: true,
child: PageView.builder(
itemBuilder: (context, index) => Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width / 2,
child: const ColoredBox(
color: Color.fromRGBO(60, 30, 10, .5),
),
),
...
See this for reference.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
