I am trying to use the Share package provided by the Flutter team. I tried implementing the package and when that didn't work I tried straight up copying and pasting their code, but got an error just the same. Unfortunately the error is not very helpful and the description of the error says "we need to explain this better". Any ideas?
Here's the package I'm using
My Code:
FlatButton(
child: Text(
'Share',
style: TextStyle(
color: Color.fromRGBO(245, 93, 62, 1.0)),
),
color: Colors.grey[100],
onPressed: () {
final RenderBox box = context.findRenderObject();
Share.share('Hello this is a test',
sharePositionOrigin:
box.localToGlobal(Offset.zero) &
box.size);
},
),
The Error:
flutter: The following assertion was thrown while handling a gesture:
flutter: type 'RenderSliverList' is not a subtype of type 'RenderBox'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 _EverythingState._buildEventCards.<anonymous closure> (package:loopt_in/widgets/everything.dart:175:43)
flutter: #1 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
flutter: #2 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:562:30)
flutter: #3 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
flutter: #4 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
flutter: #5 TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:204:7)
flutter: #6 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
flutter: #7 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:184:20)
flutter: #8 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:158:22)
flutter: #9 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:138:7)
flutter: #10 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:101:7)
flutter: #11 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:85:7)
flutter: #12 _invoke1 (dart:ui/hooks.dart:165:13)
flutter: #13 _dispatchPointerDataPacket (dart:ui/hooks.dart:119:5)
flutter: Handler: onTap
flutter: Recognizer:
flutter: TapGestureRecognizer#ecc56(debugOwner: GestureDetector, state: ready, won arena, finalPosition:
flutter: Offset(196.0, 747.5), sent tap down)
Update
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:share/share.dart';
class Everything extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _EverythingState();
}
}
class _EverythingState extends State<Everything> {
Widget _buildEventCards(BuildContext context, DocumentSnapshot document) {
var width = MediaQuery.of(context).size.width;
return Container(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 14.0),
child: Card(
elevation: 0.0,
child: Column(
children: <Widget>[
Image.asset(
document['image'],
fit: BoxFit.cover,
),
Container(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
child: Column(
children: <Widget>[
SizedBox(
height: 15.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// Icon(document['icon']),
],
),
],
),
SizedBox(
height: 10.0,
),
Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
children: <Widget>[
Chip(
backgroundColor: Colors.grey[100],
label: Text(
document['date'],
),
),
SizedBox(
width: 10.0,
),
Chip(
backgroundColor: Colors.grey[100],
label: Text(document['source']),
),
SizedBox(
width: 10.0,
),
Chip(
backgroundColor: Colors.grey[100],
label: Text(
document['location'],
),
),
],
),
SizedBox(
height: 15.0,
),
Container(
width: width,
child: Text(
document['title'],
style: TextStyle(fontSize: 24.0),
),
),
SizedBox(
height: 20.0,
),
Text(document['desc']),
SizedBox(
height: 20.0,
),
Row(
children: <Widget>[
FlatButton(
child: Text(
'More',
style: TextStyle(
color: Color.fromRGBO(118, 190, 208, 1.0)),
),
color: Colors.grey[100],
onPressed: () {
print('webview clicked');
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => WebviewScaffold(
url: document['url'],
appBar: AppBar(
title: Text(document['source']),
backgroundColor: Color.fromRGBO(
135,
142,
136,
1.0,
),
),
),
),
);
},
),
SizedBox(
width: 15.0,
),
FlatButton(
child: Text(
'Share',
style: TextStyle(
color: Color.fromRGBO(245, 93, 62, 1.0)),
),
color: Colors.grey[100],
onPressed: () {
final RenderBox box = context.findRenderObject();
Share.share('Hello this is a test',
sharePositionOrigin:
box.localToGlobal(Offset.zero) &
box.size);
},
),
],
),
],
),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: Firestore.instance.collection('stories').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildEventCards(context, snapshot.data.documents[index]),
);
});
}
// #override
// void initState() {
// // TODO: implement initState
// super.initState();
// FirebaseAdMob.instance.initialize(appId: FirebaseAdMob.testAppId);
// var bannerAd = _buildBanner()..load();
// }
}
New Error Traceback
[VERBOSE-2:shell.cc(184)] Dart Error: Unhandled exception:
MissingPluginException(No implementation found for method share on channel plugins.flutter.io/share)
#0 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:291:7)
<asynchronous suspension>
#1 Share.share (package:share/share.dart:44:20)
#2 ShareButton.build.<anonymous closure> (package:loopt_in/widgets/everything.dart:220:17)
#3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
#4 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:562:30)
#5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
#6 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
The issue in this line
RenderBox box = context.findRenderObject();
the right side return RenderSliverList and you assigning it to RenderBox that why there is a mismatch type.
What excactly you are trying to share? so I can help with that
Edit:
You need to extract share button into its own widget. Try the following complete code. It works.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:share/share.dart';
class Everything extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _EverythingState();
}
}
class _EverythingState extends State<Everything> {
Widget _buildEventCards(BuildContext context, DocumentSnapshot document) {
var width = MediaQuery.of(context).size.width;
return Container(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 14.0),
child: Card(
elevation: 0.0,
child: Column(
children: <Widget>[
Image.asset(
document['image'],
fit: BoxFit.cover,
),
Container(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
child: Column(
children: <Widget>[
SizedBox(
height: 15.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// Icon(document['icon']),
],
),
],
),
SizedBox(
height: 10.0,
),
Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
children: <Widget>[
Chip(
backgroundColor: Colors.grey[100],
label: Text(
document['date'],
),
),
SizedBox(
width: 10.0,
),
Chip(
backgroundColor: Colors.grey[100],
label: Text(document['source']),
),
SizedBox(
width: 10.0,
),
Chip(
backgroundColor: Colors.grey[100],
label: Text(
document['location'],
),
),
],
),
SizedBox(
height: 15.0,
),
Container(
width: width,
child: Text(
document['title'],
style: TextStyle(fontSize: 24.0),
),
),
SizedBox(
height: 20.0,
),
Text(document['desc']),
SizedBox(
height: 20.0,
),
Row(
children: <Widget>[
FlatButton(
child: Text(
'More',
style: TextStyle(
color: Color.fromRGBO(118, 190, 208, 1.0)),
),
color: Colors.grey[100],
onPressed: () {
print('webview clicked');
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => WebviewScaffold(
url: document['url'],
appBar: AppBar(
title: Text(document['source']),
backgroundColor: Color.fromRGBO(
135,
142,
136,
1.0,
),
),
),
),
);
},
),
SizedBox(
width: 15.0,
),
new MyButton(),
],
),
],
),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: Firestore.instance.collection('stories').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildEventCards(context, snapshot.data.documents[index]),
);
});
}
// #override
// void initState() {
// // TODO: implement initState
// super.initState();
// FirebaseAdMob.instance.initialize(appId: FirebaseAdMob.testAppId);
// var bannerAd = _buildBanner()..load();
// }
}
class MyButton extends StatelessWidget {
const MyButton({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return FlatButton(
child: Text(
'Share',
style: TextStyle(
color: Color.fromRGBO(245, 93, 62, 1.0)),
),
color: Colors.grey[100],
onPressed: () {
final RenderBox box = context.findRenderObject();
Share.share('Hello this is a test',
sharePositionOrigin:
box.localToGlobal(Offset.zero) &
box.size);
},
);
}
}
In case anyone is still having issues on this. Here is a code that works for me.
shareData(BuildContext context){
Share.share('Some text here',
subject: 'Update the coordinate!',
sharePositionOrigin: Rect.fromLTWH(left, top, width, height)
);
}
Related
Widget build(BuildContext context) {
return Scaffold(
backgroundColor:Colors.white,
body:Expanded(
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.9,
height: MediaQuery.of(context).size.height*0.22,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 36.0,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("MON COMPTE",style: TextStyle(fontSize:30,fontWeight:FontWeight.bold),),
Container(
height: 50.0,
width: 50.0,
child: FloatingActionButton(
backgroundColor: Color(0xffd57031),
onPressed: (){
},
child: Icon(Icons.help_outline,size: 30.0,),),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?3.0:1.0))
),
width: MediaQuery.of(context).size.width/2.2,
child: FlatButton(onPressed: (){
setState(() {
check = true;
});
ctrl.animateToPage(0, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("Se connecter",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?1.0:3.0))
),
width: MediaQuery.of(context).size.width/2.31,
child: FlatButton(onPressed: (){
setState(() {
check = false;
});
ctrl.animateToPage(1, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("S'inscrire",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
],
)
],
),
),
Container(
height:MediaQuery.of(context).size.height*0.78,
child: PageView(
controller: ctrl,
children: <Widget>[
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(height:20.0),
txtField("E-mail"),
SizedBox(height:20.0),
txtField("Mot de passe"),
SizedBox(height:40.0),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20.0,
spreadRadius: 5.0
)
],
),
width: MediaQuery.of(context).size.width*0.7,
height: 50.0,
child: FlatButton(onPressed: (){}, child: Text("Se connecter",style: TextStyle(color:Colors.white,)),color: Color(0xffd57031),)),
SizedBox(height:40.0),
Text('Mot de passe oublié ?',style: TextStyle(color:Color(0xffd57031),),),
Divider(color: Color(0xffd57031),thickness: 1.5,indent: 112.0,endIndent: 125,height:1,)
],
),
),
],
),
)
],
),
),
],
),
),
);
}
and there is the error
I/flutter (20272): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (20272): The following assertion was thrown building _BodyBuilder:
I/flutter (20272): Incorrect use of ParentDataWidget.
I/flutter (20272): Expanded widgets must be placed inside Flex widgets.
I/flutter (20272): Expanded(no depth, flex: 1, dirty) has no Flex ancestor at all.
I/flutter (20272): The ownership chain for the parent of the offending Expanded was:
I/flutter (20272): _BodyBuilder ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ←
I/flutter (20272): AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#9611b ink
I/flutter (20272): renderer] ← NotificationListener ← PhysicalModel ← ⋯
I/flutter (20272):
I/flutter (20272): The relevant error-causing widget was:
I/flutter (20272): Scaffold file:///Users/macbook/AndroidStudioProjects/monmercato/lib/Screens/Login.dart:37:12
You are getting the error because you are using an Expanded widget to wrap your Column.
To fix this, try:
1) Remove the Expanded widget wrapping the Column
2) If you want the Widgets to take the screen height, remove the Expanded widget and wrap your Column widget with a Container(give the container a width and height property)
Check the code below, it works fine:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor:Colors.white,
Container(
// give the container your preferred height here
height: MediaQuery.of(context).size.height,
// give the container your preferred width here
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.9,
height: MediaQuery.of(context).size.height*0.22,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 36.0,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("MON COMPTE",style: TextStyle(fontSize:30,fontWeight:FontWeight.bold),),
Container(
height: 50.0,
width: 50.0,
child: FloatingActionButton(
backgroundColor: Color(0xffd57031),
onPressed: (){
},
child: Icon(Icons.help_outline,size: 30.0,),),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?3.0:1.0))
),
width: MediaQuery.of(context).size.width/2.2,
child: FlatButton(onPressed: (){
setState(() {
check = true;
});
ctrl.animateToPage(0, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("Se connecter",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?1.0:3.0))
),
width: MediaQuery.of(context).size.width/2.31,
child: FlatButton(onPressed: (){
setState(() {
check = false;
});
ctrl.animateToPage(1, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("S'inscrire",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
],
)
],
),
),
Container(
height:MediaQuery.of(context).size.height*0.78,
child: PageView(
controller: ctrl,
children: <Widget>[
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(height:20.0),
txtField("E-mail"),
SizedBox(height:20.0),
txtField("Mot de passe"),
SizedBox(height:40.0),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20.0,
spreadRadius: 5.0
)
],
),
width: MediaQuery.of(context).size.width*0.7,
height: 50.0,
child: FlatButton(onPressed: (){}, child: Text("Se connecter",style: TextStyle(color:Colors.white,)),color: Color(0xffd57031),)),
SizedBox(height:40.0),
Text('Mot de passe oublié ?',style: TextStyle(color:Color(0xffd57031),),),
Divider(color: Color(0xffd57031),thickness: 1.5,indent: 112.0,endIndent: 125,height:1,)
],
),
),
],
),
)
],
),
),
],
),
),
);
I hope this helps.
You have to just remove First Expanded Widget.
Scaffold(
backgroundColor: Colors.white,
body: Column(// remove Expandede
children: <Widget>[
Previously i was initializing my PersonBlocProvider in my main.dart
return PersonBlocProvider(
personBloc: PersonBloc(this._apiInterface),
child: AlarmBlocProvider(
alarmBloc: AlarmBloc(this._apiInterface),
child: EventBlocProvider(
eventBloc: EventBloc(this._apiInterface),
child: MaterialApp(
title: 'Hat Mobile',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: LoginScreen(),
)
)
)
);
And using the BLOCs in another view like this:
class AlarmView extends StatelessWidget {
Widget build(BuildContext context) {
final personBlocProvider = PersonBlocProvider.of(context);
final alarmBlocProvider = AlarmBlocProvider.of(context);
return
DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10, right: 10),
child: Text(StringLiterals.ALARM_TEXT)),
Padding(
padding: EdgeInsets.only(right: 15),
child: _BuildSwitch(bloc: alarmBlocProvider))
],
title: Text(StringLiterals.PAGE_TITLE_ALARM),
bottom: MyTabBar(),
),
body: TabBarView(
children: <Widget>[
_ListPage(StringLiterals.PRESENT, personBlocProvider),
_ListPage(StringLiterals.SAFE, personBlocProvider),
_ListPage(StringLiterals.UNKNOWN, personBlocProvider),
_ListPage(StringLiterals.HOLIDAY, personBlocProvider),
],
),
),
);
}
}
This worked, but was spawning BLoCs as soon as app started and I realised i don't want that.
So i decided to move the BlocProviders from main to my view file.
my main became
return MaterialApp(
title: 'Hat Mobile',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: LoginScreen(),
);
and view:
class AlarmView extends StatelessWidget {
Widget build(BuildContext context) {
final personBlocProvider = PersonBlocProvider.of(context);
final alarmBlocProvider = AlarmBlocProvider.of(context);
return PersonBlocProvider(
personBloc: PersonBloc(BlueApiMock()),
child: AlarmBlocProvider(
alarmBloc: AlarmBloc(BlueApiMock()),
child: DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10, right: 10),
child: Text(StringLiterals.ALARM_TEXT)),
Padding(
padding: EdgeInsets.only(right: 15),
child: _BuildSwitch(bloc: alarmBlocProvider))
// child: _BuildSwitch(bloc: AlarmBloc(BlueApiMock())))
],
title: Text(StringLiterals.PAGE_TITLE_ALARM),
bottom: MyTabBar(),
),
body: TabBarView(
children: <Widget>[
_ListPage(StringLiterals.PRESENT, personBlocProvider),
_ListPage(StringLiterals.SAFE, personBlocProvider),
_ListPage(StringLiterals.UNKNOWN, personBlocProvider),
_ListPage(StringLiterals.HOLIDAY, personBlocProvider),
],
),
),
)
));
}
}
But now this is resulting in error:
I/flutter ( 6448): The following NoSuchMethodError was thrown building AlarmView(dirty):
I/flutter ( 6448): The getter 'personBloc' was called on null.
I/flutter ( 6448): Receiver: null
I/flutter ( 6448): Tried calling: personBloc
I/flutter ( 6448):
I/flutter ( 6448): When the exception was thrown, this was the stack:
I/flutter ( 6448): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 6448): #1 PersonBlocProvider.of (package:red_photon/alarm/providers/person_bloc_provider.dart:14:30)
I/flutter ( 6448): #2 AlarmView.build (package:red_photon/alarm/views/alarm_view.dart:17:51)
Why is it null now?
Yes, you cannot do that as the context you are passing will not have any bloc ancestor though, instead try wrapping DefaultTabController in a Builder Widget and use that context(it will have the bloc as ancestors in widget tree).
Example:
class AlarmView extends StatelessWidget {
Widget build(BuildContext context) {
return PersonBlocProvider(
personBloc: PersonBloc(BlueApiMock()),
child: AlarmBlocProvider(
alarmBloc: AlarmBloc(BlueApiMock()),
child: Builder(
builder: (context) {
final personBlocProvider = PersonBlocProvider.of(context);
final alarmBlocProvider = AlarmBlocProvider.of(context);
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10, right: 10),
child: Text(StringLiterals.ALARM_TEXT)),
Padding(
padding: EdgeInsets.only(right: 15),
child: _BuildSwitch(bloc: alarmBlocProvider))
// child: _BuildSwitch(bloc: AlarmBloc(BlueApiMock())))
],
title: Text(StringLiterals.PAGE_TITLE_ALARM),
bottom: MyTabBar(),
),
body: TabBarView(
children: <Widget>[
_ListPage(StringLiterals.PRESENT, personBlocProvider),
_ListPage(StringLiterals.SAFE, personBlocProvider),
_ListPage(StringLiterals.UNKNOWN, personBlocProvider),
_ListPage(StringLiterals.HOLIDAY, personBlocProvider),
],
),
),
);
},
),
),
);
}
}
This should work.
Hope it helps!
I tried something like this:
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text(widget.title),
),
child: Center(
child: Container(
child: CupertinoButton.filled(
child: const Text('Push screen'),
onPressed: () {
CupertinoNavigationBar navBar = CupertinoNavigationBar(
leading: Row(children: <Widget>[
const CupertinoNavigationBarBackButton(),
CupertinoButton(
child: const Text('Button 2'),
padding: EdgeInsets.zero,
onPressed: () {},
),
]),
);
Navigator.push(context, CupertinoPageRoute<CupertinoPageScaffold>(
builder: (_) => CupertinoPageScaffold(
navigationBar: navBar,
child: Center(child: const Text('Content')),
)
));
},
),
),
),
);
}
And when tapping the button, it fails with
I/flutter (30855): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (30855): The following NoSuchMethodError was thrown building CupertinoNavigationBarBackButton(dirty):
I/flutter (30855): The getter 'canPop' was called on null.
I/flutter (30855): Receiver: null
I/flutter (30855): Tried calling: canPop
The reason is that this code in CupertinoNavigationBarBackButton returns null
final ModalRoute<dynamic> currentRoute = ModalRoute.of(context);
I wonder why that's the case? Is it because when I push the button, context still hasn't gotten the route yet?
What's the correct way to manually add a back button?
Thanks in advance.
Here is a very simple snippet of code. I hope it helps you:
class DemoView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
leading: GestureDetector(
onTap: () {
debugPrint('Back button tapped');
},
child: Row(
children: <Widget>[
Icon(CupertinoIcons.left_chevron),
Text(
'Back',
style: TextStyle(
color: CupertinoColors.activeBlue,
),
),
],
),
),
middle: Text('Demo'),
trailing: GestureDetector(
onTap: () {
debugPrint('add icon tapped');
},
child: Icon(
CupertinoIcons.add,
color: CupertinoColors.black,
),
),
),
child: Center(
child: Text(
'Content',
style: TextStyle(fontSize: 36.0),
),
),
);
}
}
Which is the correct way to add manually back button?
I use code like this:
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text(widget.title),
leading: CupertinoNavigationBarBackButton(
onPressed: () => Navigator.of(context).pop(),
),
child: _myAppBody() // return widget
),
);
}
First of all, I'm a beginner at Flutter. I'm sending form data to login API and waiting for Success: OK message and UserID from API.
After getting UserID and Succes: OK response from API I'm sending the user to the dashboard with userID Here is my full code ;
class LoginScreen1 extends StatefulWidget {
#override
_LoginScreen1State createState() => _LoginScreen1State();
}
class _LoginScreen1State extends State<LoginScreen1> {
StreamSubscription streamSubscription;
String formMail, formSifre;
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
Login login;
Future<Login> _gonderiGetir(String formMail, String formSifre) async {
var url = 'MYURL';
var apiKey = "MYKEY";
var authPassword = this.formSifre;
var authMail = this.formMail;
debugPrint(this.formSifre);
var response = await http
.get('$url?Key=12345&mail=${this.formMail}&password=${this.formSifre}');
debugPrint("Sonuç Bekleniyor.");
if (response.statusCode == 200) {
_gelenDegeriBekle();
return Login.fromJsonMap(json.decode(response.body));
} else {
throw Exception("Baglanamadık ${response.statusCode}");
}
}
#override
void initState() {
// TODO: implement initState
super.initState();
/*_gonderiGetir(formSifre, formMail).then((gelenDeger) {
login = gelenDeger;
debugPrint(login.UserID);
});*/
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Color(0xFFF7F8FA),
child: ListView(
children: <Widget>[
Stack(
children: <Widget>[
Container(
height: 250.0,
width: double.infinity,
),
Container(
height: 300.0,
width: double.infinity,
color: Color(0xFFFED428),
),
Positioned(
top: 225.0,
left: 15.0,
right: 15.0,
child: Material(
elevation: 3.0,
borderRadius: BorderRadius.circular(7.0),
child: Container(
height: 280.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7.0),
color: Color(0xF6F6F6)),
),
)),
Positioned(
top: 75.0,
left: (MediaQuery.of(context).size.width / 2 - 50.0),
child: CircleAvatar(
radius: 50.0,
backgroundImage: NetworkImage(
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHVRLWSF79r7ABstLzXZi_pTcNkAMqx8EtWfIRZiA8mmqcl-Fsqw"),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(40, 235, 40, 15),
child: Form(
key: formKey,
autovalidate: true,
child: Column(
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
labelStyle: TextStyle(color: Color(0xFFBBBFCB)),
icon: Icon(
Icons.person,
color: Color(0xFFBBBFCB),
),
labelText: 'Email *',
),
validator: (String girilenVeri) {
if (!girilenVeri.contains("#")) {
return "Geçerli bir mail adresi giriniz.";
} else
return null;
},
controller: _usernameController,
onSaved: (deger) => formMail = deger,
),
SizedBox(
height: 10.0,
),
TextFormField(
obscureText: true,
decoration: const InputDecoration(
labelStyle: TextStyle(color: Color(0xFFBBBFCB)),
icon: Icon(
Icons.lock,
color: Color(0xFFBBBFCB),
),
labelText: 'Şifre *',
),
validator: (String girilenVeri) {
if (girilenVeri.length < 6) {
return "Şifre 6 karakterden kısa olamaz.";
} else
return null;
},
controller: _passwordController,
onSaved: (deger) => formSifre = deger,
),
],
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(40, 420, 40, 15),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: double.infinity,
height: 50,
child: RaisedButton(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Color(0xFFFED428),
onPressed: () {
if (formKey.currentState.validate()) {
formKey.currentState.save();
_gonderiGetir(formMail, formSifre);
debugPrint("OnPress Geldi");
}
},
child: Text(
"GİRİŞ",
style: TextStyle(fontSize: 20),
),
),
),
FlatButton(
onPressed: () {},
child: Text(
"Şifremi Unuttum",
style: TextStyle(
fontSize: 10, color: Color(0xFFBBBFCB)),
),
)
],
),
),
),
],
)
],
),
),
);
;
}
void _loginControl() {
if (formKey.currentState.validate()) {
formKey.currentState.save();
//formMail = _usernameController.text;
//formSifre= _passwordController.text;
debugPrint("$formSifre ve $formMail");
}
}
void _gelenDegeriBekle() {
_gonderiGetir(formSifre, formMail).then((gelenDeger) {
login = gelenDeger;
if (login.Status != null) {
debugPrint(login.UserID);
debugPrint(login.Status);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MyHomePage(),
),
);
}
});
}
}
But i'm getting this loop error:
flutter: asdasd
flutter: 387ddd00-f5ed-4c9c-87cf-45835bf77a53
flutter: OK
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.
Receiver: null
Tried calling: ancestorStateOfType(Instance of 'TypeMatcher<NavigatorState>')
#0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
#1 Navigator.of (package:flutter/src/widgets/navigator.dart:1376:19)
#2 Navigator.pushReplacement (package:flutter/src/widgets/navigator.dart:1055:22)
#3 _LoginScreen1State._gelenDegeriBekle.<anonymous closure> (package:flutter_apppp/login.dart:247:19)
#4 _rootRunUnary (dart:async/zone.dart:1132:38)
#5 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#6 _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
#7 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
#8 Future._propagateToListeners (dart:async/future_impl.dart:668:32)
#9 Future._complete (dart:async/future_impl.dart:473:7)
#10 _SyncCompleter.complete (dart:<…>
I keep getting this error message.
It looks like you have a loop that continuously runs in your widget. You're calling _gonderiGetir from _gelenDegeriBekle and also calling _gelenDegeriBekle from _gonderiGetir. So it's going to keep doing this forever, even after your widget has been removed (which is why context is null).
If you need to do something continuously, I'd recommend instead using a periodic timer to call it, and making sure that the timer is stopped when your widget is disposed!
I'm having a very weird problem with a layout. I've created a screen that is working absolutely fine in all android devices but when I run same code on iOS devices its it's messed up, am attaching screenshots of android and iOS. Here is the code for this screen. Same issue am facing in one more screen where I am having column in card widget. Please help me with this.
class _AddMoneyState extends State<AddMoney> {
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: new AppBar(
title: new Text('Add Money',
style: const TextStyle(color: Colors.white),),
),
body: new Container(
child: new ListView(
children: <Widget>[
new Container(
width: double.infinity,
height: 150.0,
padding: const EdgeInsets.all(10.0),
child: new Card(
elevation:5.0,
child: new Center(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new SizedBox(height: 30.0,),
new Text('ADD MONEY',
style: const TextStyle(color: Colors.blueGrey,
fontSize: 20.0),),
new Container(
width: 100.0,
child: new TextField(
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
decoration: const InputDecoration(
hintText: 'Enter amount'
),
),
),
new SizedBox(height:10.0),
new Text('USD', style:
const TextStyle(color: Colors.blue,
fontSize: 20.0),),
],
),
),
),
),
new SizedBox(height: 5.0,),
new Container(
width: double.infinity,
height: 350.0,
padding: const EdgeInsets.all(10.0),
child: new Card(
elevation:5.0,
child: new Center(
child: new Column(
children: <Widget>[
new SizedBox(height: 10.0,),
new Text('CARD / BANK',
style: const TextStyle(fontSize: 16.0),),
new Text('DETAILS',
style: const TextStyle(fontSize: 16.0)),
new Container(
padding: const EdgeInsets.only(left: 60.0, right: 60.0),
child: new Form(
key: _formKey,
child: new Column(
children: <Widget>[
new Theme(
data: theme.copyWith(primaryColor: Colors.blue),
child: new TextFormField(
keyboardType: TextInputType.number,
style: const TextStyle(color: Colors.black),
decoration: new InputDecoration(
labelText: 'CARD NUMBER',
labelStyle: const TextStyle(color: Colors.grey,
fontSize: 12.0)
),
validator: (val) {
return val.isEmpty
? "Please enter card number"
: null;
},
onSaved: (String value) {
this.card_number = value;
// this._data.email = value;
}
),
),
new Theme(
data: theme.copyWith(primaryColor: Colors.blue),
child: new TextFormField(
keyboardType: TextInputType.number,
style: const TextStyle(color: Colors.black),
decoration: new InputDecoration(
labelText: 'CVV/SECURITY CODE',
labelStyle: const TextStyle(color: Colors.grey,
fontSize: 12.0)
),
validator: (val) {
return val.isEmpty
? "Please enter card number"
: null;
},
onSaved: (String value) {
this.card_number = value;
// this._data.email = value;
}
),
),
new Row(
children: <Widget>[
new Flexible(
child: new Theme(
data: theme.copyWith(primaryColor: Colors.blue),
child: new TextFormField(
keyboardType: TextInputType.number,
style: const TextStyle(color: Colors.black),
decoration: new InputDecoration(
labelText: 'MONTH',
labelStyle: const TextStyle(color: Colors.grey,
fontSize: 12.0)
),
validator: (val) {
return val.isEmpty
? "Please enter month"
: null;
},
onSaved: (String value) {
this.card_number = value;
// this._data.email = value;
}
),
),
),
new SizedBox(width: 10.0,),
new Flexible(
child: new Theme(
data: theme.copyWith(primaryColor: Colors.blue),
child: new TextFormField(
keyboardType: TextInputType.number,
style: const TextStyle(color: Colors.black),
decoration: new InputDecoration(
labelText: 'YEAR',
labelStyle: const TextStyle(color: Colors.grey,
fontSize: 12.0)
),
validator: (val) {
return val.isEmpty
? "Please enter month"
: null;
},
onSaved: (String value) {
this.card_number = value;
// this._data.email = value;
}
),
),
),
],
),
],
),
),
),
new Container(
padding: const EdgeInsets.only(left: 40.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Checkbox(value: isCheck, onChanged: (bool value) {
setState(() {
isCheck = value;
});
}),
new Text("SAVE THIS CARD FOR FASTER CHECKOUT",
style: const TextStyle(fontSize: 10.0),),
],
),
),
new Container(
//width: size.width,
child: new RaisedButton(
child: new Text(
'ADD MONEY',
style: new TextStyle(
color: Colors.white
),
),
onPressed: (){
//sentMoney();
//print(Utils.token);
},
color: Colors.blueAccent,
),
margin: new EdgeInsets.only(
top: 5.0
),
),
],
),
),
),
),
],
),
),
);
}
}
Here is the logcat:
flutter: A RenderFlex overflowed by 3.4028234663852886e+38 pixels on
the bottom.
flutter:
flutter: The overflowing RenderFlex has an orientation of
Axis.vertical.
flutter: The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
flutter: black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
flutter: Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
flutter: RenderFlex to fit within the available space instead of being sized to their natural size.
flutter: This is considered an error condition because it indicates that there is content that cannot be
flutter: seen. If the content is legitimately bigger than the available space, consider clipping it with a
flutter: ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
flutter: like a ListView.
flutter: The specific RenderFlex in question is:
flutter: RenderFlex#34c92 relayoutBoundary=up1 OVERFLOWING
flutter: creator: Column ← Center ← DefaultTextStyle ← AnimatedDefaultTextStyle ←
flutter: _InkFeatures-[GlobalKey#0628f ink renderer] ← NotificationListener<LayoutChangedNotification> ←
flutter: CustomPaint ← _ShapeBorderPaint ← PhysicalShape ← _MaterialInterior ← Material ← Padding ← ⋯
flutter: parentData: offset=Offset(118.0, 0.0) (can use size)
flutter: constraints: BoxConstraints(0.0<=w<=347.0, 0.0<=h<=122.0)
flutter: size: Size(111.0, 122.0)
flutter: direction: vertical
flutter: mainAxisAlignment: center
flutter: mainAxisSize: max
flutter: crossAxisAlignment: center
flutter: verticalDirection: down
flutter:
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
flutter:
════════════════════════════════════════════════════════════════════════════════════════════════════
Here are the screenshots
I got the issue, I was overriding fonts and the fonts that I was using were working perfectly in android but in iOS it was not working. I just commented this line in main.dart --
//fontFamily: 'DINLightAlternate'
And now its working fine in iOS devices too.