我有一個在 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,
),
),
),
),
],
);
});
}
}
我已經嘗試直接在 onTaps 內部呼叫 setState 方法,或者只是將按鈕移出站點,或者在構建方法開始時將另一個布林值設定為構建方法之外的布林值,但是沒有任何效果。
預先感謝您的回答。
uj5u.com熱心網友回復:
我也是 Flutter 的新手,但是當我遇到類似情況時,我用 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,
),
),
),
),
],
);});
});
}
}
希望這對你也有效。
uj5u.com熱心網友回復:
請注意,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,
),
),
)
,
)
,
]
,
);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/476547.html