I have a googlemap located on containers in a pageview... When u swipe between the pages that contain these googlemap widgets, the pagesnapping breaks... so inside my code when I do
class Homepage extends StatelessWidget {
#override build(BuildContext context){
return PageView(
children: <Widget>[
Container(color:Colors.red),
Container(color:Colors.green),
Container(color:Colors.blue),
Container(color:Colors.yellow),
Container(color:Colors.pink),
// Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
// Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
// Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
// Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),))
],
);
}
This, it works fine and all the pages snap perfectly.. However when I uncomment the GoogleMap widgets like so:
class Homepage extends StatelessWidget {
#override build(BuildContext context){
return PageView(
children: <Widget>[
// Container(color:Colors.red),
// Container(color:Colors.green),
// Container(color:Colors.blue),
// Container(color:Colors.yellow),
// Container(color:Colors.pink),
Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)),
Container(child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),))
],
);
}
}
The PageView works for a while but breaks (on IOS) and this error is (sometimes) shown in the console:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: 'package:flutter/src/gestures/converter.dart': Failed assertion: line 155 pos 18: '!state.down': is not true.
#0 _AssertionError._doThrowNew (dart:core/runtime/liberrors_patch.dart:40:39)
#1 _AssertionError._throwNew (dart:core/runtime/liberrors_patch.dart:36:5)
#2 PointerEventConverter.expand (package:flutter/src/gestures/converter.dart:155:18)
#3 _SyncIterator.moveNext (dart:core/runtime/libcore_patch.dart:152:12)
#4 ListQueue.addAll (dart:collection/queue.dart:715:25)
#5 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:83:27)
#6 _rootRunUnary (dart:async/zone.dart:1136:13)
#7 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#8 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
#9 _invoke1 (dart:ui/hooks.dart:223:10)
#10 _dispatchPointerDataPacket (dart:ui/hooks.dart:144:5
Anyone seen and fixed this?
Thanks for your attention..
John.
I had a similar issue working with google map in pageview but after searching online I got a solution that finally worked
All I did was put the google map in a stateful widget, used the with AutomaticKeepAliveClientMixin and #override bool get wantKeepAlive => true; and called in the required widget
This is the stateful widget containing the google map
class GoogleMapWidget extends StatefulWidget{
const GoogleMapWidget({Key? key}) : super(key: key);
#override
_GoogleMapWidgetState createState() => _GoogleMapWidgetState();
}
class _GoogleMapWidgetState extends State<GoogleMapWidget> with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
return Container(
child:GoogleMap(initialCameraPosition: CameraPosition(target:LatLng(0, 0)),)
);
}
}
Then you can call it from your Homepage like so
class Homepage extends StatelessWidget {
#override
build(BuildContext context){
return PageView(
children: <Widget>[
GoogleMapWidget(),
GoogleMapWidget(),
],
);
}
}
I hope this is the answer you're looking for
don't use Pageview instead use PageView.builder and then create a global list
List latLong = [
// pass all google maps and latLong values here
];
then on itemBuilder pass the latlong according to index and don't forget to turn gestureDetector on your googleMaps else it'll also scroll the map
Related
I want to obtain RenderObject of SelectableText because I want obtain RenderBox of the text, which, to my understanding, is obtainable via RenderObject.
So, I try to use GlobalKey to access the RenderObject by using this GlobalKey().currentContext?.findRenderObject()
But what I got is not what I want...
This is the demo program:
class Demo extends StatefulWidget {
const Demo({Key? key}) : super(key: key);
#override
State<Demo> createState() => _DemoState();
}
class _DemoState extends State<Demo> {
final _selectableTextKey = GlobalKey();
#override
Widget build(BuildContext context) {
return SelectableText(
'This is a test',
key: _selectableTextKey,
onTap: () {
print(
'render object == ${_selectableTextKey.currentContext?.findRenderObject()}');
},
);
}
}
This is the output in the console:
flutter: render object == RenderSemanticsAnnotations#52070 relayoutBoundary=up4
As illustrated in the screenshot of the DetailTree
I want the RenderObject of green arrow's, but I got red arrow's instead.
Using GlobalKey to obtain RenderObject then to access the RenderBox is all I know so far, so I don't have other idea to try...
I am currently working on this tutorial in which transfers a variable to an external file to another (with a callback)
but i have this error :
======== Exception caught by gesture ===============================================================
The following NoSuchMethodError was thrown while handling a gesture:
The method 'call' was called on null.
Receiver: null
Tried calling: call(3)
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 Son.build.<anonymous closure> (package:montest/son.dart:24:21)
#2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
#3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:607:11)
#4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#cf4d9
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(178.3, 84.9)
button: 1
sent tap down
====================================================================================================
son.dart
///
/// Inside the Child Widget
///
import 'package:flutter/material.dart';
// Step 1: Define a Callback.
typedef void IntCallback(int id);
class Son extends StatelessWidget {
// Step 2: Configre the child to expect a callback in the constructor(next 2 lines):
final IntCallback onSonChanged;
Son({ #required this.onSonChanged });
int elementId = 3;
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
// Step 3: On specific action(e.g onPressed/
// onTap/onLoad.. onWhatEver) trigger the callback
// with the data you want to pass to the parent.
// Data will be passed as parameter(see elementId):
onSonChanged(elementId);
// Done in the child.
},
child: Text('Click me to call the callback!'),
);
}
}
///
///////////////
parent.dart
import 'son.dart';
///
/// Inside the Parent Widget
///
import 'package:flutter/material.dart';
class Father extends StatefulWidget {
#override
_FatherState createState() => _FatherState();
}
class _FatherState extends State<Father> {
// Step 1 (optional): Define a Global variable
// to store the data comming back from the child.
int id;
// Step 2: Define a function with the same signature
// as the callback, so the callback will point to it,
// this new function will get the data from the child,
// set it to the global variable (from step 1)
// in the parent, and then update the UI by setState((){});
void updateId(int newId) {
setState(() {
id = newId;
});
}
#override
Widget build(BuildContext context) {
return Container(
// Step 3: Construct a child widget and pass the
child: Son(
// Many options to make onSonChanged points to
// an executable code(function) within memory
// called 'updateId':
//
// 1st option:
onSonChanged: (int newId) {
updateId(newId);
},
// 2nd option: onSonChanged: updateId,
// 3rd option: onSonChanged: (int newId) => updateId(newId)
// So each time the 'onSonChanged' called by the action
// we defined inside the child, a new data will be
// passed to this parent.
)
);
}
}
Thanks for your help
make id nullable and check it.
try this
import 'package:flutter/material.dart';
typedef void IntCallback(int id);
class Son extends StatelessWidget {
final IntCallback onSonChanged;
Son({required this.onSonChanged});
int elementId = 3;
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
onSonChanged(elementId);
},
child: Text('Click me to call the callback!'),
);
}
}
class Father extends StatefulWidget {
#override
_FatherState createState() => _FatherState();
}
class _FatherState extends State<Father> {
int? id;
void updateId(int newId) {
setState(() {
id = newId;
});
}
#override
Widget build(BuildContext context) {
return Column(
children: [
id == null ? Text(" son value: null") : Text("son value: $id"),
Container(
child: Son(
onSonChanged: (int newId) {
updateId(newId);
},
),
),
],
);
}
}
There is an interesting problem. I'm using Flutter 2.0 in my app. It has a bottom navigation bar. When I push to the new screen using "Navigator.of(context, rootNavigator: true)" along with the new screen, the screen that provides navigation is also rebuilding.
CategoriesView build() method
#override
Widget build(BuildContext context) {
print("Building: CategoryView");
return mobileBody;
}
ProductDetailView build() method
#override
Widget build(BuildContext context) {
print("Building: ProductDetailView");
return mobileBody;
}
When i use the "context.rootNavigator.pushNamed(ProductDetailView.route);" in CategoryView output is:
I/flutter (21910): Building: ProductDetailView
I/flutter (21910): Building: CategoryView
Without rootNavigator output is (context.navigator.pushNamed(ProductDetailView.route);):
I/flutter (21910): Building: ProductDetailView
Navigator extensions:
extension NavigationExtension on BuildContext {
NavigatorState get rootNavigator => Navigator.of(this, rootNavigator: true);
NavigatorState get navigator => Navigator.of(this);
}
Why is this happening? How can I prevent this?
I have met the same issue too, currently use a StatefulWidget wrapper for it.
class WrapperStateless extends StatefulWidget {
const WrapperStateless({Key key}) : super(key: key);
#override
_WrapperStatelessState createState() => _WrapperStatelessState();
}
class _WrapperStatelessState extends State<WrapperStateless> {
TabA tabA;
#override
void initState() {
super.initState();
tabA = TabA();
}
#override
Widget build(BuildContext context) {
// return tabA;
return tabA;
}
#override
void didUpdateWidget(WrapperStateless oldWidget) {
super.didUpdateWidget(oldWidget);
// setState(() {});
}
}
My app uses a hierachy of UI designs and extended designs for the correct layout (naturally).
One of my hierachies is a simple 3 layer approach:
HomePage (content) ->
UiBaseMain (structure for content) ->
UiBase (scaffolding)
Details: (and an MVCE) - I have tried narrowing down to the simplest form to get repeatedly throw this error.
Tested on both physical devices and AVD, both give a Stack Overflow error.
UiBase (ui_component_base.dart) (which all layouts are based on)
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class UiBase extends StatelessWidget {
final Widget widget;
const UiBase({Key key, this.widget})
: super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
width: double.infinity,
child: widget),
);
}
}
UiBaseMain (ui_main_navbar_appbar.dart) (where all Main UI content is shown with i.e. Dashboard, settings, etc which ideally alsop contains a small logo ontop, a BottomNavigationBar, etc)
import 'package:mytestapp/ui/design/ui_component_base.dart';
import 'package:flutter/widgets.dart';
class UiBaseMain extends StatefulWidget {
final Widget widget;
const UiBaseMain({Key key, this.widget}) : super(key: key);
#override
_UiBaseMain createState() => _UiBaseMain();
}
class _UiBaseMain extends State<UiBaseMain> {
#override
Widget build(BuildContext context) {
return UiBase(
widget: widget,
);
}
}
Finally, HomePage (ui_homepage.dart) (which is a content page, should show user content, etc)
import 'package:mytestapp/ui/design/ui_main_navbar_appbar.dart';
import 'package:flutter/widgets.dart';
class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
#override
_HomePage createState() => _HomePage();
}
class _HomePage extends State<HomePage> {
#override
Widget build(BuildContext context) {
return UiBaseMain(
widget: Text("test"),
);
}
}
Problem
Using the above structure, I consistently get the following Stack Overflow error
======== Exception caught by widgets library =======================================================
The following StackOverflowError was thrown building Material(type: canvas, color: Color(0xfffafafa), dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#1c4c4], _EffectiveTickerMode], state: _MaterialState#b2ccd):
Stack Overflow
The relevant error-causing widget was:
Scaffold file:///C:/Users/CybeX/mytestapp/mytestapp-mobile-flutter/lib/ui/design/ui_component_base.dart:14:12
When the exception was thrown, this was the stack:
#0 _WordWrapParseMode.values (package:flutter/src/foundation/diagnostics.dart:776:6)
#1 _SyncIterator.moveNext (dart:core-patch/core_patch.dart:165:25)
#2 Iterable.length (dart:core/iterable.dart:429:15)
#3 _PrefixedStringBuilder._finalizeLine (package:flutter/src/foundation/diagnostics.dart:856:30)
#4 _PrefixedStringBuilder.write (package:flutter/src/foundation/diagnostics.dart:973:9)
...
====================================================================================================
======== Exception caught by widgets library =======================================================
The method 'call' was called on null.
Receiver: null
Tried calling: call()
The relevant error-causing widget was:
Scaffold file:///C:/Users/CybeX/mytestapp/mytestapp-mobile-flutter/lib/ui/design/ui_component_base.dart:14:12
====================================================================================================
======== Exception caught by widgets library =======================================================
The method 'call' was called on null.
Receiver: null
Tried calling: call()
The relevant error-causing widget was:
Scaffold file:///C:/Users/CybeX/mytestapp/mytestapp-mobile-flutter/lib/ui/design/ui_component_base.dart:14:12
====================================================================================================
Question
Is this an issue my side or is this an issue others can confirm and infact a bug in the Flutter framework?
You have to pass here widget.widget because it is a stateful widget, no? : return UiBase(
widget: widget,
);
Sorry not convenient to write from phone.
I'm Using provider in initState() to call the api but if I use listen:false then it does not update UI and it always shows me loader but if I use listen:true then app works fine but in the terminal it shows me exception and tells me write listen:false.
My UI,
class ChopperNewsCard extends StatefulWidget {
#override
_ChopperNewsCardState createState() => _ChopperNewsCardState();
}
class _ChopperNewsCardState extends State<ChopperNewsCard> {
ScrollController scrollController = ScrollController();
int currentPage = 5;
ChopperApiStore _apiStore = ChopperApiStore();
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_apiStore = Provider.of<ChopperApiStore>(context,);//<--- here it tells me to write listen:false
});
_apiStore.getResponse(currentPage);
scrollController.addListener(() {
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
if (currentPage < 20) {
currentPage = currentPage + 5;
_apiStore.getResponse(currentPage);
}
}
});
}
#override
void dispose() {
scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return Observer(builder: (context) {
return Container(
height: height * 0.37,
width: double.infinity,
child: _apiStore.res.articles == null
? CircularProgressIndicator()
: ListView.builder(...),
);
});
}
}
api calling class,
class ChopperApiStore extends _ChopperApiStore with _$ChopperApiStore{}
abstract class _ChopperApiStore with Store{
ApiCall apiCall = ApiCall();
#observable
ChopperNews res = ChopperNews();
#action
Future<void> getResponse(int page) async {
var data = await apiCall.getNews(page);
res = data;
}
}
the error I'm getting,
======== Exception caught by scheduler library =====================================================
The following assertion was thrown during a scheduler callback:
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing `listen: false`.
To fix, write:
Provider.of<ChopperApiStore>(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.
The context used was: ChopperNewsCard(dependencies: [MediaQuery], state: _ChopperNewsCardState#8f6cd)
'package:provider/src/provider.dart':
Failed assertion: line 262 pos 7: 'context.owner.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'
When the exception was thrown, this was the stack:
#2 Provider.of (package:provider/src/provider.dart:262:7)
#3 _ChopperNewsCardState.initState.<anonymous closure> (package:fruitley/week-5/bonus/chopper/widgets/chopper_news_card.dart:32:28)
#4 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
#5 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1063:9)
#6 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:971:5)
...
I think if you want to use listen:true to have the build method called you are suppose to override didChangeDependencies rather then initState Checkout this article it might help https://medium.com/swlh/flutter-provider-and-didchangedependencies-15678f502262
ok I'm dumb. I didn't even need to use addPostFrameCallback.
I just removed it and if I want to use provider outside of widget tree that I must use listen:false as it was showing in the exception so now everything makes sense.