У меня есть стек, который создается внутри FutureBuilder, частью стека является ElevatedButton, который фокусируется на моем текущем местоположении на карте, что также является частью стека.
Моя идея заключается в том, что когда я нажимаю на маркер моей карты, для логического значения устанавливается значение false (onMarkerTap), поэтому кнопка исчезает, а когда я снова нажимаю на карту (onTap), кнопка появляется снова. Я делаю это с помощью метода setState().
Проблема в том, что весь этот код работает без проблем при использовании режима отладки, но как только я использую режим выпуска, кнопка исчезает и больше не появляется.
class MapComponent extends StatefulWidget {
const MapComponent({Key? key}) : super(key: key);
@override
State<MapComponent> createState() => MapSampleState();
}
class MapSampleState extends State<MapComponent> {
...
bool _focusLocationVisible = true;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
super.dispose();
}
void setFocusButton(bool state){
setState(() {
_focusLocationVisible = state;
});
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getDataFuture,
builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return (const Center(child: CircularProgressIndicator()));
} else {
...
}
var size = MediaQuery.of(context).size;
return Stack(
children: [
FlutterMap(
mapController: mapController,
layers: [
TileLayerOptions(...),
LocationMarkerLayerOptions(),
MarkerClusterLayerOptions(
...
onMarkerTap:(Marker marker)=>{
setFocusButton(false)
},
popupOptions: PopupOptions(
popupController: _popupController,
popupSnap: PopupSnap.mapBottom,
popupAnimation: PopupAnimation.fade(
duration: Duration(milliseconds: 200)),
popupBuilder: (_, marker) {
return DraggableScrollableSheet(...);
}),
),
],
options: MapOptions(
onTap: (TapPosition, LatLang) =>
{
_popupController.hideAllPopups(),
setFocusButton(true),
},
...
plugins: [
MarkerClusterPlugin(),
LocationMarkerPlugin(
//centerOnLocationUpdate: _centerOnLocationUpdate,
centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
centerAnimationDuration: Duration(milliseconds: 500),
)
],
),
),
if (_focusLocationVisible == true)
Positioned(
right: 20,
bottom: 40,
//right: _buttonrightPosition,
//bottom: _buttonbottomPosition,
child: AnimatedOpacity(
opacity: _focusLocationVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: FloatingActionButton(
backgroundColor: Theme.of(context).bottomAppBarColor,
heroTag: null,
onPressed: () async {
// Location location = Location();
// LocationData curloc = await location.getLocation();
_centerCurrentLocationStreamController.add(16);
//mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
},
child: const Icon(
Icons.my_location,
color: Colors.white,
),
),
),
),
],
);
});
}
}
Я уже пытался вызвать метод setState непосредственно внутри onTaps, или просто переместив кнопку просто за пределы сайта, или установив другое логическое значение со значением логического значения вне метода сборки в начале метода сборки, но ничего не работало.
Заранее спасибо за ваши ответы.
я также новичок в флаттере, но когда я столкнулся с подобной ситуацией, я обернул виджет с помощью ValueListenableBuilder и установил логическое значение как ValueNotifier. и это сработало для меня.
class MapComponent extends StatefulWidget {
const MapComponent({Key? key}) : super(key: key);
@override
State<MapComponent> createState() => MapSampleState();
}
class MapSampleState extends State<MapComponent> {
...
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
ValueNotifier<bool> _focusLocationVisible = ValueNotifier(true);
return FutureBuilder(
future: _getDataFuture,
builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return (const Center(child: CircularProgressIndicator()));
} else {
...
}
var size = MediaQuery.of(context).size;
return ValueListenableBuilder(
valueListenable: _focusLocationVisible,
builder: (context, _value, _) {return Stack(
children: [
FlutterMap(
mapController: mapController,
layers: [
TileLayerOptions(...),
LocationMarkerLayerOptions(),
MarkerClusterLayerOptions(
...
onMarkerTap:(Marker marker)=>{
_focusLocationVisible.value = false
},
popupOptions: PopupOptions(
popupController: _popupController,
popupSnap: PopupSnap.mapBottom,
popupAnimation: PopupAnimation.fade(
duration: Duration(milliseconds: 200)),
popupBuilder: (_, marker) {
return DraggableScrollableSheet(...);
}),
),
],
options: MapOptions(
onTap: (TapPosition, LatLang) =>
{
_popupController.hideAllPopups(),
_focusLocationVisible.value = false,
},
...
plugins: [
MarkerClusterPlugin(),
LocationMarkerPlugin(
//centerOnLocationUpdate: _centerOnLocationUpdate,
centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
centerAnimationDuration: Duration(milliseconds: 500),
)
],
),
),
if (_focusLocationVisible == true)
Positioned(
right: 20,
bottom: 40,
//right: _buttonrightPosition,
//bottom: _buttonbottomPosition,
child: AnimatedOpacity(
opacity: _focusLocationVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: FloatingActionButton(
backgroundColor: Theme.of(context).bottomAppBarColor,
heroTag: null,
onPressed: () async {
// Location location = Location();
// LocationData curloc = await location.getLocation();
_centerCurrentLocationStreamController.add(16);
//mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
},
child: const Icon(
Icons.my_location,
color: Colors.white,
),
),
),
),
],
);});
});
}
}
Надеюсь, это сработает и для вас.
Будьте осторожны, setState может перезагрузить Futurebuilder. В соответствии с рекомендациями, используйте виджет композиции агрессивно. ValueNotifier хорош для небольшого проекта, но для большого проекта ваш код будет трудно понять.
class MapComponent extends StatelessWidget {
const MapComponent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getDataFuture,
builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
if (snapshot.connectionState = ConnectionState.waiting) {
return (const Center(child: CircularProgressIndicator()));
} else if (!snapshot.hasData) {
return Text("No data");
}
final data = snapshot.data;
var size = MediaQuery
.of(context)
.size;
return BuildStack(yourData: data);
});
}
}
class BuildStack extends StatefulWidget {
final dynamic yourData;
const BuildStack({Key? key, required this.yourData}) : super(key: key);
@override
_BuildStackState createState() => _BuildStackState();
}
class _BuildStackState extends State<BuildStack> {
late bool _focusLocationVisible = true;
@override
void initState() {
super.initState();
_focusLocationVisible = true;
}
void setFocusButton() {
setState(() {
_focusLocationVisible = !_focusLocationVisible;
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
FlutterMap(
mapController: mapController,
layers: [
TileLayerOptions(...),
LocationMarkerLayerOptions(),
MarkerClusterLayerOptions(
onMarkerTap: (Marker marker) =>
setFocusButton()
,
popupOptions: PopupOptions(
popupController: _popupController,
popupSnap: PopupSnap.mapBottom,
popupAnimation: PopupAnimation.fade(
duration: const Duration(milliseconds: 200)),
popupBuilder: (_, marker) {
return DraggableScrollableSheet(...);
}),
),
],
options: MapOptions(
onTap: (TapPosition, LatLang) =>
{
_popupController.hideAllPopups(),
setFocusButton(),
},
plugins: [
MarkerClusterPlugin(),
LocationMarkerPlugin(
//centerOnLocationUpdate: _centerOnLocationUpdate,
centerCurrentLocationStream: _centerCurrentLocationStreamController
.stream,
centerAnimationDuration: const Duration(
milliseconds: 500),
)
],
),
),
if (_focusLocationVisible)
Positioned(
right: 20,
bottom: 40,
//right: _buttonrightPosition,
//bottom: _buttonbottomPosition,
child: AnimatedOpacity(
opacity: _focusLocationVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: FloatingActionButton(
backgroundColor: Theme
.of(context)
.bottomAppBarColor,
heroTag: null,
onPressed: () async {
// Location location = Location();
// LocationData curloc = await location.getLocation();
_centerCurrentLocationStreamController.add(16);
//mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
},
child: const Icon(
Icons.my_location,
color: Colors.white,
),
),
)
,
)
,
]
,
);
}
}