英文:
Keep general dialog showing while allowing selection and clicking on the screen
问题
我有一个屏幕上的可长按列表项的列表。我需要实现的用户界面是从顶部向下滑入一个包含可应用于屏幕上选定项的操作的操作小部件。
我已经选择了这些项,但问题是,一旦我选择了第一项并从顶部显示滑入对话框,我就不能再点击屏幕上的任何部分,因为对话框的屏障已经阻塞了整个屏幕。
我该怎么做才能去掉那个屏障,以便我仍然可以点击列表项而不会关闭对话框。
只有对话框上的操作应该能够关闭对话框。
以下是我当前的对话框设置:
Future<T?> showNonBlockingTopModalSheet<T>(BuildContext context, Widget child,
{bool barrierDismissible = false}) {
return showGeneralDialog<T?>(
context: context,
barrierDismissible: barrierDismissible,
barrierColor: Colors.transparent,
transitionDuration: const Duration(milliseconds: 250),
pageBuilder: (context, _, __) => child,
transitionBuilder: (context, animation, secondaryAnimation, child) {
return SlideTransition(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Material(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [child],
),
)
],
),
position: CurvedAnimation(parent: animation, curve: Curves.easeOutCubic)
.drive(
Tween<Offset>(
begin: const Offset(0, -1.0),
end: Offset.zero,
),
),
);
},
);
}
英文:
I have a List of long clickable ListItems on screen. The UI I am required to achieve is to slide in an actions widget from the top down that contains actions that can be applied on the selected items on screen.
I have selected the items, but the issue is that once I select the first item and display the slide in dialog from top, I can no longer click on any part of the screen again because the dialog barrier has blocked the entire screen.
What can I do to remove that barrier so I can still click on the list items without dismissing the dialog.
Only the actions on the dialog should be able to dismiss the dialog.
Here is my dialog setup currently:
Future<T?> showNonBlockingTopModalSheet<T>(BuildContext context, Widget child,
{bool barrierDismissible = false}) {
return showGeneralDialog<T?>(
context: context,
barrierDismissible: barrierDismissible,
barrierColor: Colors.transparent,
transitionDuration: const Duration(milliseconds: 250),
pageBuilder: (context, _, __) => child,
transitionBuilder: (context, animation, secondaryAnimation, child) {
return SlideTransition(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Material(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [child],
),
)
],
),
position: CurvedAnimation(parent: animation, curve: Curves.easeOutCubic)
.drive(
Tween<Offset>(
begin: const Offset(0, -1.0),
end: Offset.zero,
),
),
);
},
);
}
答案1
得分: 1
以下是您要翻译的内容:
"The showGeneralDialog creates a new page on top of our page, because of which we can't control our page which is behind the new one.<br>
I have implemented the code as per your needs. You may need to modify it as per your requirements. It will help you proceed further.
We are using Stack, along with Animated Positioned for your use case.<br>
Stack has two children, first one is the visible list items and second one is the AnimatedPositioned widget.<br>
The example is inspired from AnimatedPositioned Demo<br>
Here is your code.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showModel = false;
@override
Widget build(BuildContext context) {
final listItems = [0,1,2,3,4,5,6,7,8,9.10,11,12,13,14,15,16,17,18];
return Scaffold(
appBar: !showModel ? AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
):PreferredSize(child: SizedBox(), preferredSize: Size(0,0),),,
body: Stack(
children: <Widget>[
ListView(
children: listItems.map((e) {
return Container(
height: 50,
child: Text('Widget number $e'));
}).toList(),
),
AnimatedPositioned(
curve: Curves.easeOutCubic,
height: 200,
bottom: showModel ?
MediaQuery.of(context).size.height - 200:
MediaQuery.of(context).size.height,
duration: const Duration(milliseconds: 250),
child: Container(
height: MediaQuery.of(context).size.height - 100,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: const Center(child: Text("I am modal prompt")),
),)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
showModel = !showModel;
});
},
child: Text("Toggle"),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
如果您需要更多帮助,请随时提问。
英文:
The showGeneralDialog creates a new page on top of our page, because of which we can't control our page which is behind the new one.<br>
I have implemented the code as per your needs. You may need to modify it as per your requirements. It will help you proceed further.
We are using Stack, along with Animated Positioned for your use case.<br>
Stack has two children, first one is the visible list items and second one is the AnimatedPositioned widget.<br>
The example is inspired from AnimatedPositioned Demo<br>
Here is your code.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showModel = false;
@override
Widget build(BuildContext context) {
final listItems = [0,1,2,3,4,5,6,7,8,9.10,11,12,13,14,15,16,17,18];
return Scaffold(
appBar: !showModel ? AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
):PreferredSize(child: SizedBox(), preferredSize: Size(0,0),),,
body: Stack(
children: <Widget>[
ListView(
children: listItems.map((e) {
return Container(
height: 50,
child: Text('Widget number $e'));
}).toList(),
),
AnimatedPositioned(
curve: Curves.easeOutCubic,
height: 200,
bottom: showModel ?
MediaQuery.of(context).size.height - 200:
MediaQuery.of(context).size.height,
duration: const Duration(milliseconds: 250),
child: Container(
height: MediaQuery.of(context).size.height - 100,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: const Center(child: Text("I am modal prompt")),
),)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
showModel = !showModel;
});
},
child: Text("Toggle"),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论