Why I still got error functio at flutter?
I'd removed the old function and used new function, but it was still got old function.
In my main.dart, I tried to called LoginScreen
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'yocamp',
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: mobileBackgroundColor,
),
home: LoginScreen(),
);
}
}
But it was called MobileScreenLayout
home: const ResponsiveLayout(
mobileScreenLayout: MobileScreenLayout(),
webScreenLayout: WebScreenLayout(),
),
In my LoginScreen
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 32),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//sva image
SvgPicture.asset(
'assets/yocampLogo.svg',
//color: primaryColor,
height: 64,
),
const SizedBox(height: 64),
//text field input for email
//text field input for password
//button login
//Transitioning to singing up
],
),
),
));
}
}
in the MobileScreenLayout
class MobileScreenLayout extends StatelessWidget {
const MobileScreenLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('This is mobile'),
));
}
}
I want to show svg, but it's still show This is mobile
where has problems?
Related
I would like to have a persistent container occupy the space about my material Scaffolds AppBar. I would like the Scaffold to resize to take up the available space.
When I try to do this, my Scaffold continues to be the height of the entire screen, and it is simply pushed lower, with a portion overflowing off the screen.
Is there a way I can have the Scaffold to resize to the available space?
Here is what I have coded so far...
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return PersistenTopBar(
child: Scaffold(
appBar: AppBar(
title: const Text("Test App"),
),
body: Container(),
),
);
}
}
class PersistenTopBar extends StatelessWidget {
final Widget child;
const PersistenTopBar({Key? key , required this.child }) : super(key: key);
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return Column(
children: [
Container(
width: double.infinity,
height: 200,
color: Colors.red,
),
SizedBox(
width: mediaQuery.size.width,
height: mediaQuery.size.height,
child: child,
),
],
);
}
}
You could also create a CustomAppBar that would take as children a topChild and an appBar.
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final double height;
final Widget topChild;
final AppBar appBar;
const CustomAppBar(
{Key? key,
this.height = 200.0,
required this.topChild,
required this.appBar})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: topChild),
appBar,
],
);
}
#override
Size get preferredSize => Size.fromHeight(height);
}
Full code sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
topChild: Container(color: Colors.red),
appBar: AppBar(title: const Text('My awesome Test App')),
),
body: const Center(
child: Text(
"Test App",
style: TextStyle(fontSize: 32.0),
),
),
);
}
}
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final double height;
final Widget topChild;
final AppBar appBar;
const CustomAppBar(
{Key? key,
this.height = 200.0,
required this.topChild,
required this.appBar})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: topChild),
appBar,
],
);
}
#override
Size get preferredSize => Size.fromHeight(height);
}
the available space = mediaQuery.size.height - the Height of the Container above the appBar so the SizedBox under the appBar wil be :
SizedBox(
width: mediaQuery.size.width,
height: mediaQuery.size.height - 200,
child: child,
),
the result:
or you can wrap your SizedBox with Expanded Widget :
Expanded(
child: SizedBox(
width: mediaQuery.size.width,
child: child,
),
),
the same result :
I follow this stack overflow link to restrict bold text globally on whole app. Now when i try to implement this to restrict bold text as well as to restrict big text size on specific screen then only one restriction works. Means if i put restrict bold text first and restrict big text size second then restrict bold text doesn't work and if i put restrict big text size first and restrict bold text second then restrict bold text works how to solve this issue? Below is the sample dart code till now i what i have tried.
main.dart
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(''),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Center(child: Text('Text')),
const SizedBox(
height: 50.0,
),
Center(
child: TextButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const NextPage()));
},
child: const Text('Move')),
)
],
),
);
}
}
class NextPage extends StatefulWidget {
const NextPage({Key? key}) : super(key: key);
#override
_NextPageState createState() => _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return MediaQuery(
data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window)
.copyWith(boldText: false), // Restrict bold text
child: MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.5), // Restrict bigger text size
child: Scaffold(
appBar: AppBar(
title: const Text(''),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Center(child: Text('Text')),
],
),
),
),
);
}
}
you have two options to achieve your goal.
1 - use only one MediaQuery and put all your settings in that like: .copyWith(boldText: false, textScaleFactor: 1.5)
2 - wrap your inner MediaQuery in a Builder.
I'm using a nested MaterialApp such that, FirstMaterialApp has SecondMaterialApp as its child. I'm facing an issue when calling showDialog from SecondMaterialApp, that is it appears on the entire screen as if it is opened from the FirstMaterialApp.
I want that the dialog remains confined to the boundaries of the SecondMaterialApp.
In the image, I have intentionally stretched the Dialog across the width so that it is apparent that it covers the FirstMaterialApp.
First MaterialApp
class FirstMaterialApp extends StatelessWidget {
const FirstMaterialApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'First Material App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First App Scaffold'),
),
body: Center(
child: DeviceFrame(
device: Devices.ios.iPhone12, screen: const SecondMaterialApp()),
));
}
}
Second MateriaApp
class SecondMaterialApp extends StatelessWidget {
const SecondMaterialApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Second Materia App', home: SecondScaffold());
}
}
class SecondScaffold extends StatelessWidget {
const SecondScaffold({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 40.0),
child: Scaffold(
appBar: AppBar(
title: const Text('Second App Home'),
),
body: Center(
child: TextButton(
child: const Text('Open Dialog'),
onPressed: () async {
await showDialog(
context: context,
builder: (buildContext) => CustomDialog());
},
),
),
),
);
}
}
class CustomDialog extends StatelessWidget {
const CustomDialog({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Dialog(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const [
Text(
'Dialog',
style: TextStyle(fontSize: 20.0),
),
Text(
'Message Text',
),
],
),
);
}
}
Found the solution by using a showDialog parameter named useRootNavigator. Setting it to false provided the required results.
Now the dialog is confined to the boundaries of child MaterialApp and the backgroundOverly from showDialog covers only the second material app.
-> use Your Second File code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SecondMaterialApp extends StatelessWidget {
const SecondMaterialApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Second Materia App', home: SecondScaffold());
}
}
class SecondScaffold extends StatelessWidget {
const SecondScaffold({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 40.0),
child: Scaffold(
appBar: AppBar(
title: const Text('Second App Home'),
),
body: Center(
child: TextButton(
child: const Text('Open Dialog'),
onPressed: () async {
await showDialog(
context: context,
builder: (buildContext) => const CustomDialog());
},
),
),
),
);
}
}
class CustomDialog extends StatelessWidget {
const CustomDialog({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CupertinoAlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const \[
Text(
'Dialog',
style: TextStyle(fontSize: 20.0),
),
Text(
'Message Text',
),
\],
),
);
}
}
create material before dialog
return Material(child: Dialogue());
I want to implement something like an Instagram profile page with the NestedScrollView widget. So I combine this with a TabBar widget. I have two tabs. Detail and comments. Then I have other widgets on top of the TabBar. Everything works as expected so far. But the problem starts when I scroll. Even though there is nothing inside my tabs, NestedScrollView scrolls too much, and my TabBar widget comes to the top of the screen. In Instagram, if you have no photos, you can not scroll the page. But in my application, I can scroll. And this is the behavior I want to prevent. How can I do this? I also share my codes and screenshots of the unwanted behavior.
This is the page
This is the over scroll even though there is nothing to show inside the tab bar
These are the codes:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Home Page"),
),
body: DefaultTabController(
length: 2,
child: NestedScrollView(
headerSliverBuilder: (context, isScrolled) {
return [
SliverToBoxAdapter(
child: Container(
margin: const EdgeInsets.all(16),
child: const Placeholder(
fallbackHeight: 300,
fallbackWidth: double.infinity,
color: Colors.amberAccent,
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: StickyTabBarDelegate(
child: const TabBar(
labelColor: Colors.black,
tabs: [
Tab(text: "Detail"),
Tab(text: "Comments"),
],
),
),
)
];
},
body: const TabBarView(
children: [
DetailTab(),
CommentsTab(),
],
),
),
),
);
}
}
class DetailTab extends StatelessWidget {
const DetailTab({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container();
}
}
class CommentsTab extends StatelessWidget {
const CommentsTab({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container();
}
}
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar child;
StickyTabBarDelegate({required this.child});
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: Colors.white,
child: child,
);
}
#override
double get maxExtent => child.preferredSize.height;
#override
double get minExtent => child.preferredSize.height;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
I've create simple PageView app to test multiple pages.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final firstPage = FirstPage(key: Key("FirstPage"));
final secondPage = SecondPage(key: Key("SecondPage"));
debugPrint("_MyHomePageState.build");
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
children: <Widget>[
firstPage,
secondPage,
],
),
);
}
}
class FirstPage extends StatelessWidget {
FirstPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
class SecondPage extends StatelessWidget {
SecondPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("SecondPage.build");
return Container(
child: Center(
child: Text("Second Page"),
),
);
}
}
Even thought _MyHomePageState.build has been shown only once, FirstPage.build and SecondPage.build were printed on every page changes.
What I'd like to prevent unnecessary page draw, how can I accomplish this?
You can achieve so by using
1. const keyword
Make your widgets accept to be const:
class FirstPage extends StatelessWidget {
const FirstPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
and call it with const keyword:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
children: <Widget>[
const firstPage(),
const secondPage(),
],
),
);
2. AutomaticKeepAliveClientMixin
Convert your StatelessWidget to StatefullWidget.
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
Extends AutomaticKeepAliveClientMixin on StatefullWidget created State.
class _FirstPageState extends State<FirstPage> with AutomaticKeepAliveClientMixin {
Call super on the build method.
#override
Widget build(BuildContext context) {
super.build(context);
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
Override wantKeepAlive getter with true returned value.
#override
bool get wantKeepAlive => true;
And then your widget tree won't dispose of this widget so it won't rebuild over and over.
Code Example:
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage>
with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
#override
bool get wantKeepAlive => true;
}
3. MVVM Architecture with any State-management solution you like
It will save your state on ViewModel away from the View, so your UI can rebuild itself anytime it wants with no worries about your State because the ViewModel is still the same.
You should always imagine that your build() methods (for both StatefulWidget and StatelessWidget) are being called 60 times per second, so they should be simple and idempotent. Anything else should be moved into a StatefulWidget initState() and friends.
It's easy!
pageController can help you.
Just in your _MyHomePageState
Declare final pageController = PageController(keepPage: false);
And in your PageView
PageView(
controller: pageController,
children: <Widget>[
firstPage,
secondPage,
],
)
Good Luck.