Closed pishguy closed 1 year ago
Hi @pishguy, thanks for opening the issue.
Please check this section of the readme, where we describe that you can't directly access the Backdrop.of(context)
within the same widget context, in which you create the BackdropScaffold
.
You
Backdrop.of(context)
into a separate widget (i.e. create a new StatelessWidget and put the GestureDetector stuff into it), orGestureDetector
(in this case) in a Builder
widget. Like that you have a "new" context, from which you can access Backdrop.of(context)
@WieFel hi again :)
could you help me whats the correct context
in this code? i want to close Backdrop
manually:
Builder
context:return ValueListenableBuilder<bool>(
valueListenable: wm.bottomSheetVisibility,
builder: (_, bool visibility, __) {
return Builder(
builder: (context) {
return WillPopScope(
onWillPop: () async {
if (visibility) {
wm.onChangeBottomSheetVisibility(context: context, visibility: false);
return Future.value(false);
}
wm.onChangeBottomSheetVisibility(context: context, visibility: true);
return Future.value(true);
},
child: BackdropScaffold(
revealBackLayerAtStart: true,
frontLayerActiveFactor: .9,
resizeToAvoidBottomInset: false,
onBackLayerConcealed: () {
wm.bottomSheetVisibility.value = true;
},
onBackLayerRevealed: () {
wm.bottomSheetVisibility.value = false;
},
onChangeBottomSheetVisibility
method:
void onChangeBottomSheetVisibility({
required BuildContext context,
required bool visibility,
}) {
bottomSheetVisibility.value = visibility;
Backdrop.of(context).fling();
}
ValueListenableBuilder
context:return ValueListenableBuilder<bool>(
valueListenable: wm.bottomSheetVisibility,
builder: (context, bool visibility, __) {
return WillPopScope(
onWillPop: () async {
if (visibility) {
wm.onChangeBottomSheetVisibility(context: context, visibility: false);
return Future.value(false);
}
wm.onChangeBottomSheetVisibility(context: context, visibility: true);
return Future.value(true);
},
child: BackdropScaffold(
context
:builder: (_, bool visibility, __) {
return WillPopScope(
onWillPop: () async {
if (visibility) {
wm.onChangeBottomSheetVisibility(visibility: false);
return Future.value(false);
}
wm.onChangeBottomSheetVisibility(visibility: true);
return Future.value(true);
},
onChangeBottomSheetVisibility
method:
void onChangeBottomSheetVisibility({required bool visibility}) {
bottomSheetVisibility.value = visibility;
Backdrop.of(context).fling();
}
i'm opening frontLayer
by clicking on subHeader
widget, thanks so much
I think the problem here is that the context
that you pass to Backdrop.of(context).fling();
in all cases is not the correct one. They are ALL from "above" (outside) the BackdropScaffold
. But what you need is a context
from ONE LEVEL BELOW the BackdropScaffold
.
So, having the ValueListenableBuilder
inside the BackdropScaffold
(e.g. in the body
, if possible) would solve the problem in my opinion. Then, you wouldn't even need an additional Builder
, but using the context
of the ValueListenableBuilder
would be enough.
@WieFel if i put ValueListenableBuilder
inside BackdropScaffold
how can i close frontLayer
manually with WillPopScope
?
my widget has a default context
and i tested that before.
is this your meant?
@override
Widget build(ILocationScreenWidgetModel wm) {
return ValueListenableBuilder<bool>(
valueListenable: wm.bottomSheetVisibility,
builder: (context, bool visibility, __) {
return WillPopScope(
onWillPop: () async {
if (visibility) {
wm.bottomSheetVisibility.value = false;
Backdrop.of(context).fling();
return Future.value(false);
}
wm.bottomSheetVisibility.value = true;
return Future.value(true);
},
child: BackdropScaffold(
...
onBackLayerConcealed: () {
wm.bottomSheetVisibility.value = true;
},
onBackLayerRevealed: () {
wm.bottomSheetVisibility.value = false;
},
problem is closing the frontLayer
inside WillPopScope
widget not inside of subHeader
return ValueListenableBuilder<bool>(
valueListenable: wm.bottomSheetVisibility,
builder: (_, bool visibility, __) {
return Builder(
builder: (context) {
return WillPopScope(
onWillPop: () async {
if (visibility) {
wm.bottomSheetVisibility.value = false;
Backdrop.of(context).fling();
return Future.value(false);
}
wm.bottomSheetVisibility.value = true;
return Future.value(true);
},
child: BackdropScaffold(
//...
subHeader: BackdropSubHeader(
leading: Builder(
builder: (context) {
return IconButton(
onPressed: () => Backdrop.of(context).fling(),
icon: const Icon(Icons.close_rounded),
);
},
),
Could you briefly explain again what you are trying to achieve? I am a bit confused... Could you maybe provide a simpler example of what your use case is?
as far as I understand, you have the following:
BackdropScaffold
with an initially "open" front layer (?)is that correct?
@WieFel
In the default state, the frontLayer
widget is hidden, and when I click a button, its state changes to visible. The first fundamental issue was that when I pressed the back button on the phone, I expected to be able to return the frontLayer
widget to the hidden state, which was not happening.
The second issue is that when the frontLayer
widget is in the hidden state, I should be able to return to the previous screen by clicking the back button.
These two states were not implementable outside of the library, so I modified the library itself to address these issues.
please check this pull request: https://github.com/fluttercommunity/backdrop/pull/135
I created a small example app for you, which does the following:
BackdropScaffold
import 'package:backdrop/backdrop.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Backdrop Demo',
home: Scaffold(
appBar: AppBar(
title: const Text("My App"),
),
body: Center(
// Builder necessary here to be able to use Navigator.push (as we are in the same widget as
// our MaterialApp)
child: Builder(builder: (context) {
return ElevatedButton(
child: const Text("Open Backdrop Page"),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MyCustomPage(),
),
),
);
}),
),
),
);
}
}
class MyCustomPage extends StatelessWidget {
const MyCustomPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BackdropScaffold(
appBar: AppBar(
title: const Text("Backdrop Example"),
),
concealBacklayerOnBackButton: false,
revealBackLayerAtStart: true,
backLayerBackgroundColor: Colors.grey.shade300,
backLayer: Center(
// Builder necessary here to be able to call Backdrop.of(context), as we are inside the same
// widget as our BackdropScaffold
child: Builder(
builder: (context) {
return ElevatedButton(
onPressed: () => Backdrop.of(context).concealBackLayer(),
child: const Text("Conceal Back Layer"),
);
},
),
),
subHeader: const BackdropSubHeader(
title: Text("Sub Header"),
),
frontLayer: const Center(
child: Text("Front Layer"),
),
);
}
}
In my opinion, it should not be necessary to make any change to the library for this. Hope this helps...
@WieFel i checked your code, thanks
closing frontLayer
doesn't work every where such as my project, i tires to use Builder
but it couldn't resolve py problem
Yes, but you need to put it in the correct place. As I said, it needs to be BELOW the BackdropScaffold
in the widget tree. Otherwise, Backdrop.of(context)
won't find anything...
how can i Manually opening Backdrop to show
frontLayer
without using like sample code action such as:this is my code and i get
Null check operator used on a null value
error on this line of codeBackdrop.of(context).fling()
: