flutter statfulWidget refresh twice - flutter

return MaterialApp(
home: Scaffold(
body: RefreshIndicator(
key: _globalKey,
onRefresh: refresh,
child: Sub(),
),
),
);
there is simple refreshindicator and sub Widget
class Sub extends StatefulWidget {
#override
_SubState createState() => _SubState();
}
class _SubState extends State<Sub> {
#override
Widget build(BuildContext context) {
print('sub');
return Container(
color: Colors.amber,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 300,
color: Colors.blue,
),
Container(
height: 300,
color: Colors.red,
),
Container(
height: 300,
color: Colors.green,
),
],
),
),
);
}
}
Sub Widget print "sub" when it is built
the point is when i touch or just slightly drag page(not enough call refreshindicator) sub widget is rebuilt TWICE. i don't know why and i don't know how can i slove.
(statelesswidget can solve that problem but i need to use statefulwidget)

It depends what you want to achieve without re-building but alternate I used was for flutter charts. Create a object Sub sub1=Sub(); , somewhere outside build() or intiState() , then this widget will not rebuild again and values will be same.

Related

How to make the application responsive using Stack and Positoned - Flutter

How to use Stack and Positioned to add a shape in the SafeArea, I tried to change the color of the AppBar and connect to the shape and add mediaQuery, but still not on every screen it will be properly connected. So how to get a svg photo on the entire surface of SafeArea, and to make it responsive without using appbar, is it necessary to get the effect like in the picture below?(the code gives the effect as in the picture, but it is not responsive and consists of two parts, and I would like one part and get responsive)
Any help very much appreciated.
class Shape extends StatelessWidget {
static Route route() {
return MaterialPageRoute<void>(builder: (_) => Shape());
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
elevation: 0,
actions: [],
),
body: _profilePage(context),
);
}
Widget _profilePage(BuildContext context) {
return SafeArea(
child: Align(
child: Center(
child: Stack(
children: <Widget>[
Positioned(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height,
bottom: MediaQuery.of(context).size.width * 0.6,
child: _curved(context),
),
],
),
),
),
);
}
Widget _curved(BuildContext context) {
return SvgPicture.asset(
'assets/images/shape_purple.svg',
color: Colors.blue,
allowDrawingOutsideViewBox: true,
);
}
Use FitteBox Widget instead
FittedBox(
child: Image.asset('assets/images/background.png'),
fit: BoxFit.fill,
// decoration: BoxDecoration(
// color: Colors.white),
),

Flutter: I want to display "Grid View" and other widgets together on the screen

I was able to display the child widgets in a grid using the GridView widget,
Widgets such as text and GridView widgets together on one screen
How can I display it?
For example
//sign_in_page.dart
class SignInPage extends StatelessWidget {
void _signInAnonymously() async {
final authResult=await FirebaseAuth.instance.signInAnonymously();
print('${authResult.user.uid}');
}
#override
Widget build(BuildContext context) {
List<Widget> list1=[
SizedBox(
width:50.0,
height:50.0,
child:Container(
color:Colors.blue,
),
),
SizedBox(
width:100.0,
height:100.0,
child:Container(
color:Colors.red,
),
),
SizedBox(
width:100.0,
height:100.0,
child:Container(
color:Colors.green,
),
),
SizedBox(
width:100.0,
height:100.0,
child:Container(
color:Colors.yellow,
),
),
];
return Scaffold(
appBar: AppBar(
title: Text('title'),
elevation: 10.0,
),
//body: buildContent(),
body:Column( //←This will give an error.
children: [
Text('Description of this GridView'),
GridView.count(
crossAxisCount: 3,
children: list1
),
],
),
backgroundColor: Colors.grey[300],
);
}
//main.dart
import 'package:flutter/material.dart';
import 'app/sign_in/sign_in_page.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title:'title',
theme:ThemeData(
primarySwatch: Colors.indigo,
),
home:SignInPage(),
);
}
}
I want to display the text and grid view,
but when I try to display it using the Column widget as above,
I get an error.
Is there any suitable widget to use in this situation?
I guess You should wrap Your GridView.count() with an Expanded() to specify the height, like
Expanded(
child: GridView.count()
)

Flutter - Stack with Scaffold

I'm currently using Scaffold with BottomNavigationBar in a project and need to display a separated widget on top of all that.
Tried to create a Stack on the build return and put this widget and the Scaffold as the children, but the widget is simply not displayed (not showed at all)! There isn't any error messages either.
What could be wrong? Or there is any other approach? (calling AlertDialog won't work for this purpose).
Defining the Stack on the body of the Scaffold didn't work also, as it need a list for the BottomNavigationBar.
Widget build(BuildContext context) {
var Test = Center(
child: SizedBox(width: 100, height: 100,
child: Container(
color: Colors.blue,
child: Text("Test"),),),);
return Stack(
alignment: Alignment.center,
children: [
Test,
Scaffold(
appBar: ..... (rest of the code)
It is because your Scaffold is drawn over your Test widget. Stack takes multiple children and orders them from bottom to top. So the first item is the bottom-most and the last is the top-most. Try the following:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Scaffold(
appBar: AppBar(title: Text('Hi')),
),
TestWidget(),
],
),
);
}
}
class TestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
color: Colors.blue,
child: Center(
child: Text("Test"),
),
);
}
}
As #HBS mentioned, the problem was caused by the Stack ordering, but the fixing can be achieved just by changing the Widget order:
Widget build(BuildContext context) {
var Test = Center(
child: SizedBox(width: 100, height: 100,
child: Container(
color: Colors.blue,
child: Text("Test"),),),);
return Stack(
alignment: Alignment.center,
children: [
Scaffold(
appBar: ..... (rest of the code),
Test,
],

Which layout structure should I code to match my app design

For my new Flutter project I've done some research on layouts, however it still is a bit vague.
Here is the layout I'd like to create:
After some research and watching some videos, it seems this is the MaterialApp code:
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Color(0xFF0E2E40),
title: Text('City Discovery'),
actions: [
Image.asset(
'assets/images/logoicon.png',
width: 35,
)
],
),
body: ListView(
children: [
introSection,
Image.asset(
'assets/images/barman.png',
width: 600,
height: 240,
fit: BoxFit.cover,
),
crimeSection,
mysterySection,
bottomSection,
],
),
),
);
}
But now defining the layout of the different Sections is quite hard.
From what I can tell, there should be:
ListView to make my page scrollable, which it should be
introSection: Container for XYZ with 2 rows for 2 text sections.
Image
crimeSection: Container for XYZ with 3 rows for 2 text sections and button. First text section divided into 2 colums for icon and text
mysterySection: Container for XYZ with 2 rows for 2 text sections. First text section divided into 2 columns for icon and text
bottomSection: Tabs? Although tabs only seem to be part of the appbar, so not sure what the alternative is
The closest example I could find, however changing the code doesn't get me anywhere:
https://github.com/flutter/website/blob/master/examples/layout/lakes/step6/lib/main.dart
For some reason containers can only have 1 child, so that probably means I need a row in my container which then has children which then has 2 childs for both text sections? Incredibly hard to code some simple UI.
If someone can help me with the code for the introSection and the bottomSection, I can probably work out the rest myself.
I recommend to create components folder for reusable widgets, as buttons, logos, text, etc.
If you have a widget that does not used in other components, you can separate it in the same file but use underscore, to make this widget private (It will be visible only inside this file). All that will make your code more readable.
About bottom tabs.
If you want to use it as bottom tabs, you can put it in bottomNavigationBar parameter of Scaffold widget. If you need to use in inside the ListView, it possible but you need to pass the exact height of the tab, because TabView trying to expand as much as possible, same as ListView.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutExample(),
);
}
}
class LayoutExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _BottomNavigationBar(),
body: ListView(
children: <Widget>[
_IntroSection(),
Placeholder(fallbackHeight: 200),
_CrimeSection(),
_MysterySection()
],
),
);
}
}
class _IntroSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('Intro text1'),
Text('Intro text2')
],
),
);
}
}
class _CrimeSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('CrimeSection'),
);
}
}
class _MysterySection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('MysterySection'),
);
}
}
class _BottomNavigationBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
);
}
}

Can touch gestures be passed to sibling widget(s)?

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: MaterialButton(
height: 100,
color: Colors.grey,
child: Text("DSG"),
onPressed: () {
print("Drawer sent gesture");
},
),
),
drawer: Container(
height: 300,
decoration: BoxDecoration(
color: Colors.yellow,
),
child: Center(
child: MaterialButton(
height: 100,
color: Colors.grey,
child: Text("DKG"),
onPressed: () {
print("Drawer kept gesture");
},
),
),
),
);
}
}
I know that the IgnorePointer & AbsorbPointer widgets can be used to pass gestures from parent to child & vice versa, resp. but what if I want to pass to a sibling widget, e.g., from drawer to body?
Only gestures belonging to the 1st child of 1 sibling should be passed to the other, e.g., I am asking that "DSG" & "DKG" both be clickable once the drawer is opened, i.e., gestures should pass through the drawer scrim.