When I`m focusing the Autocomplete widget, the parent starts rebuilding and doesn't stop. Nobody seems to have a similar problem. The Widget used to be split in two Statefull widgets, but for testing it's now one. It seems that it only occurs in overlays, because when I open the Widget with the router, the problem doesn't persist. The bigger problem is, that it is impossible to call onSelected or onChanged.
import 'dart:async';
import 'package:dartz/dartz.dart' hide State;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_frontend/domain/my_location/my_location.dart';
import 'package:flutter_frontend/l10n/app_strings.dart';
import 'package:flutter_frontend/presentation/core/style.dart';
import 'package:flutter_frontend/presentation/core/utils/geo/search_completion.dart';
import 'package:flutter_frontend/presentation/pages/core/widgets/Overlays/my_location_form/cubit/my_locations_form_cubit.dart';
import 'package:flutter_frontend/presentation/pages/core/widgets/styling_widgets.dart';
import 'package:flutter_frontend/presentation/pages/core/widgets/stylings/coordinates_picker_with_adress_autocomplete.dart';
import '../../../../../core/utils/geo/osm_extensions/utilities.dart';
class MyLocationFormOverlay {
MyLocationFormOverlay({MyLocation? myLocation, required BuildContext context}) {
final OverlayState overlayState = Overlay.of(context)!;
OverlayEntry? overlayEntry;
overlayEntry =
OverlayEntry(builder: (context) => DismissibleOverlay(overlayEntry: overlayEntry!, child: MyLocationForm(location: myLocation,),));
overlayState.insert(overlayEntry);
}
}
class MyLocationForm extends StatefulWidget {
MyLocationForm({Key? key, MyLocation? location}) : super(key: key);
@override
State<MyLocationForm> createState() => _MyLocationFormState();
}
class _MyLocationFormState extends State<MyLocationForm> {
// this attribute tells us wheter the address is on cooldown
bool isCooldown = false;
// cooldownduration in Milliseconds
static const int cooldownDuration = 1000;
Timer? timer;
List<SearchInfoDetailed> _searchInfoOtions = <SearchInfoDetailed>[];
static String _displayStringForOption(SearchInfoDetailed option) {
return option.addressDetailed.toString();
}
static GlobalKey _formKey = GlobalKey<FormState>();
final controller_name = TextEditingController();
final controller_longitude = TextEditingController();
final controller_latitude = TextEditingController();
@override
Widget build(BuildContext context) {
return BasicContentContainer(
child_ren: right(
BlocProvider(
create: (context) => MyLocationsFormCubit(),
child: BlocConsumer<MyLocationsFormCubit, MyLocationsFormState>(
listenWhen: (p,c) => p.runtimeType != c.runtimeType,
listener: (context, state) {
if(state is MyLocationFormAdding){
controller_name.text = (state as MyLocationFormAdding).location.name.getOrEmptyString();
controller_longitude.text = (state as MyLocationFormAdding).location.longitude.toString();
controller_latitude.text = (state as MyLocationFormAdding).location.latitude.toString();
setState(() {});
}
},
buildWhen: (p, c) => p.runtimeType != c.runtimeType,
builder: (context, state) {
return Form(
key: _formKey,
child: Column(
children: [
Text(AppStrings.addLocation, style: AppTextStyles.stdLittleHeading,),
FullWidthPaddingInput(
labelText: AppStrings.name,
controller: controller_name,
hintText: AppStrings.name,
onChanged: (value) => _formCubit(context).changeName(value),
),
_buildAdressAutocomplete(context),
_buildCoordFields(context),
//_buildCoordinatesPickerAndAutoCompleteAdress(context)
],
),
);
}
),
)
)
);
}
MyLocationsFormCubit _formCubit(BuildContext context) {
return context.read<MyLocationsFormCubit>();
}
// ----------------------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------- WIDGETS --------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------------------------
Autocomplete<SearchInfoDetailed> _buildAdressAutocomplete(BuildContext context) {
print("rebuid");
return Autocomplete<SearchInfoDetailed>(
fieldViewBuilder:
(BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
return FullWidthPaddingInput(
labelText: AppStrings.address,
hintText: AppStrings.address,
fieldFocusNode: fieldFocusNode,
controller: fieldTextEditingController,
);
},
displayStringForOption: _displayStringForOption,
optionsBuilder: (TextEditingValue textEditingValue) async {
if(this.isCooldown){
return _searchInfoOtions;
}
// this sets the cooldown
Timer(Duration(milliseconds: cooldownDuration), () async { this.isCooldown = false; });
this.isCooldown = true;
//--------
// check whether the value is empty
if (textEditingValue.text == '') {
return const Iterable<SearchInfoDetailed>.empty();
}
// get suggestion
_searchInfoOtions = await addressSuggestionDetailed(textEditingValue.text);
//setState( (){});
return (_searchInfoOtions);
},
// set coordinates
onSelected: (SearchInfoDetailed selection) {
_formCubit(context).changeAddress(selection.addressDetailed.toString());
_formCubit(context).changeLatitude(selection.point?.latitude?? 0);
_formCubit(context).changeLongitude(selection.point?.longitude?? 0);
// TODO: add only jena here!
controller_longitude.text = selection.point?.longitude.toString() ?? '';
controller_latitude.text = selection.point?.latitude.toString() ?? '';
},
// we can generate an custom view of the options
);
}
ConstrainedBox _buildCoordFields(BuildContext context) {
return ConstrainedBox(constraints: BoxConstraints(maxHeight: 56),
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(child: CoordinatesPickerInput(
textEditingControllerLongi: controller_longitude,
labeltext: "longitude",
onChanged: (value2) =>
_formCubit(context).changeLongitude(double.parse(value2 == "" ? '0' : value2)),)),
Flexible(child: CoordinatesPickerInput(
textEditingControllerLongi: controller_latitude,
labeltext: "Latitude",
onChanged: (value2) => _formCubit(context).changeLatitude(double.parse(value2 == "" ? '0' : value2)),)),
],
),);
}
}