How to display custom widget? - flutter

I have a problem in my Flutter app with implement my custom Widget LifeViewList(). When I try do it createState()_HomePageState need some arguments, when I do it then I get a worrnig “Don’t put any logic in createState” .
class HomePage extends StatefulWidget {
const HomePage(
{ Key? key,
required this.user,
}) : super(key: key);
final User user;
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late ScrollController _scrollController;
double _scrollControllerOffset = 0.0;
_HomePageState(this.lifeView);
void _scrollListener() {
setState(() {
_scrollControllerOffset = _scrollController.offset;
});
}
#override
void initState() {
_scrollController = ScrollController();
_scrollController.addListener(_scrollListener);
super.initState();
}
final LifeView lifeView;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
CustomScrollView(
controller: _scrollController,
slivers: [
const LogoBanner(),
const Topic('How do you feel today?'),
const EmotionGrid(),
const SliverToBoxAdapter(
child: SizedBox(height: 20),
),
const Topic('A place to think about yourself.'),
LifeViewList(
LifeView(
title: lifeView.title,
image: lifeView.image,
id:lifeView.id,
),
),
const SingOutButton(),
],
),
FadeAppBar(scrollOffset: _scrollControllerOffset)
],
),
);
}
}
What I have to change ?

To access your widget variables in your state you can do widget.variable within your state class.
For example using user:
class HomePage extends StatefulWidget {
const HomePage({ Key? key, required this.user,}) : super(key: key);
final User user;
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Text(widget.user.username);
}
}

Related

Accessing a text field controller within another widget in Flutter?

Say I've created a file info_card.dart that I want to use to get the name of a user with the following code:-
import 'package:flutter/material.dart';
class InfoCard extends StatefulWidget {
const InfoCard({ Key? key }) : super(key: key);
#override
State<InfoCard> createState() => _InfoCardState();
}
class _InfoCardState extends State<InfoCard> {
final _nameController = TextEditingController();
#override
void dispose() {
_nameController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return TextField(
controller: _nameController
);
}
}
And then I create a completely different file, home_page.dart for example:-
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({ Key? key }) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: InfoCard(),
);
}
}
How would I access the text controller within the InfoCard() widget, and say store it in a variable so that I could write it to a database? I'm really struggling with this as simply trying to use InfoCard()._nameController doesn't seem to work.
You could create the controller in the home page instead and pass it to the infocard. for example:
class HomePage extends StatefulWidget {
const HomePage({ Key? key }) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _nameController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: InfoCard(controller: _nameController ),
);
}
#override
void dispose() {
_nameController.dispose();
super.dispose();
}
}
and
class InfoCard extends StatefulWidget {
final TextEditingController controller;
const InfoCard({ Key? key, required this.controller}) : super(key: key);
#override
State<InfoCard> createState() => _InfoCardState();
}
class _InfoCardState extends State<InfoCard> {
#override
Widget build(BuildContext context) {
return TextField(
controller: widget.controller
);
}
}
There are many ways to achieve that in Flutter, the simplest thing you can do:
Instead of creating the controller inside InfoCard, inject it to it by its constructor. So your file will look like this:
class InfoCard extends StatefulWidget {
const InfoCard( this._nameController , { Key? key,}) : super(key: key);
final TextEditingController _nameController;
#override
State<InfoCard> createState() => _InfoCardState();
}
class _InfoCardState extends State<InfoCard> {
#override
Widget build(BuildContext context) {
return TextField(
controller: widget._nameController,
);
}
}
Create a controller in HomePage and pass it to InfoCard, thus, you'll have a reference to that controller in HomePage. So your file will look like this:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController _infoCardController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: InfoCard(_infoCardController),
);
}
}
Now pass that controller reference _infoCardController wherever you need it, and use simply as
print(_infoCardController.text)
Here i Solve this problem you can follow these steps:
just click the button and check the controller result in the console window
HomePage Code:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController textController = TextEditingController();
void getText(){
print("entered text "+ textController.text);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InfoCard(textController),
ElevatedButton(onPressed: getText, child: Text("Press Here !")),
],
)),
);
}
}
InfoCard Page:
import 'package:flutter/material.dart';
class InfoCard extends StatefulWidget {
final TextEditingController textController ;
const InfoCard(#required this.textController);
#override
State<InfoCard> createState() => _InfoCardState();
}
class _InfoCardState extends State<InfoCard> {
// final _nameController = TextEditingController();
#override
void dispose() {
widget.textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey,
child: TextField(
controller: widget.textController
),
);
}
}

Prevent children from rebuilding in SliverList

Minimum example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
body: CustomScrollView(
slivers: [Example()],
),
));
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
#override
State<Example> createState() => ExampleState();
}
class ExampleState extends State<Example> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
return SliverList(
delegate: SliverChildListDelegate(const <Widget>[
SizedBox(
height: 1400,
),
CheckboxWidget()
], addAutomaticKeepAlives: true));
}
#override
bool get wantKeepAlive => true;
}
class CheckboxWidget extends StatefulWidget {
const CheckboxWidget({Key? key}) : super(key: key);
#override
State<CheckboxWidget> createState() => _CheckboxWidgetState();
}
class _CheckboxWidgetState extends State<CheckboxWidget> {
late bool _personalData = false;
#override
Widget build(BuildContext context) {
return Checkbox(
checkColor: Colors.black,
onChanged: (bool? value) {
setState(() {
_personalData = value!;
});
},
value: _personalData,
);
}
}
If you click the checkbox, then scroll out of view and then back in to view.. The box becomes unchecked. This is because the widget rebuilds...setting the _personalData to false. I would of thought addAutomaticKeepAlives would prevent the widget rebuilding and keep the state of the checkbox. How do I prevent CheckboxWidget from rebuilding?
Firstly, I will choose state management or passing value to the CheckboxWidget. To answer this question, we need to save (keep alive) the state of CheckboxWidget. Therefore, we need to use AutomaticKeepAliveClientMixin on _CheckboxWidgetState instead of parent widget.
class CheckboxWidget extends StatefulWidget {
const CheckboxWidget({Key? key}) : super(key: key);
#override
State<CheckboxWidget> createState() => _CheckboxWidgetState();
}
class _CheckboxWidgetState extends State<CheckboxWidget>
with AutomaticKeepAliveClientMixin {
late bool _personalData = false;
#override
Widget build(BuildContext context) {
super.build(context);
return Checkbox(
checkColor: Colors.black,
onChanged: (bool? value) {
setState(() {
_personalData = value!;
});
},
value: _personalData,
);
}
#override
bool get wantKeepAlive => true;
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
#override
State<Example> createState() => ExampleState();
}
class ExampleState extends State<Example> {
#override
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildListDelegate(
const <Widget>[
SizedBox(
height: 1400,
),
CheckboxWidget()
],
),
);
}
}

How to use get_it for Provider.of<ExampleProvider>(context)?

I am new to flutter and I am trying to use get_it package for DI. I want to understand how can I replace my dependance on the Inherited Widget with get_it.
My code looks like this:
I have a locator file which initialises the locator instance and its setup.
locator.dart file:
final locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton<ExampleProvider>(() => ExampleProvider());
}
example_provider.dart:
class ExampleProvider with ChangeNotifier {
bool _value = false;
bool get value => _value;
set setValue(bool newValue) {
_value = newValue;
notifyListeners();
}
}
This is the HomePage where provide the ChangeNotifierProvider with ExampleProvider to the child widget.
home_page.dart file:
class HomePage extends StatefulWidget {
final String title;
const HomePage({Key? key, required this.title}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _exampleProvider = locator.get<ExampleProvider>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
key: Key('issue_list_screen_column'),
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ChangeNotifierProvider(
create: (context) => _exampleProvider,
child: ExampleWidget(
key: Key('example_widget'),
),
),
],
),
appBar: AppBar(
title: Text(widget.title),
),
);
}
}
This is the ExampleWidget where I want to use the locator instead of Provider.of<ExampleProvider>(context)
example_widget.dart file:
class ExampleWidget extends StatefulWidget {
const ExampleWidget({
Key? key,
}) : super(key: key);
#override
_ExampleWidgetState createState() => _ExampleWidgetState();
}
class _ExampleWidgetState extends State<ExampleWidget> {
#override
Widget build(BuildContext context) {
// How do I use locator over here with context??
final _exampleProvider = Provider.of<ExampleProvider>(context);
return Switch(
value: _exampleProvider.value,
onChanged: (newValue) {
themeProvider.setValue = newValue;
},
);
}
}
So, I want to use locator for the line final _exampleProvider = Provider.of<ExampleProvider>(context); in ExampleWidget. How can I do that?
It does not work like this: final _exampleProvider = locator.get<ExampleProvider>();
try this
final _exampleProvider = locator.get<ExampleProvider>();

Flutter: Parts of a widget do not show up

I have this Flutter code sample.
class HomePage extends StatefulWidget {
final String title;
const HomePage({Key? key, required this.title}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(flex: 1, child: SideActivityBar()),
// The wiget Text('Initial') does not show up!
Expanded(flex: 4, child: MainPanel(color: Colors.blue.shade100, page: Text('Initial'))),
],
);
}
}
class MainPanel extends StatefulWidget {
final Widget page;
final Color color;
const MainPanel({Key? key, required this.color, required this.page}) : super(key: key);
#override
State<MainPanel> createState() => _MainPanelState();
}
class _MainPanelState extends State<MainPanel> {
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
color: widget.color,
child: widget.page,
);
}
}
The widget Text('Initial') does not show up though I can see MainPanel showing up. What am I missing or doing wrong?

Can I use for loop to create class?

I create swipe app for swipe Page1(), Page2() in main.dart which class Page1(), Page2() show in pages.dart. All code I use from this tutorial (github).
I want to create 30 pages. Can I use for loop to create 30 class ?
main.dart
class _MyHomePageState extends State<MyHomePage> {
int _seletedItem = 0;
var _pages = [Page1(), Page2()];
var _pageController = PageController();
pages.dart
class Page1 extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text('First Page', style: TextStyle(fontSize: 50.0),),),);
}
}
class Page2 extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text('Second Page',style: TextStyle(fontSize: 50.0),),),);
}
}
You can do it like this example here i am passing index as param to page but you can pass your custom data from your custom list too.
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _seletedItem = 0;
var _pageController = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page Controller looop - Demo'),
),
body: PageView(
children: List<Widget>.generate(1000,(i) => Page(i:i);,
onPageChanged: (index) {
setState(() {
_seletedItem = index;
});
},
controller: _pageController,
),
);
}
}
class Page extends StatelessWidget {
final i;
const Page({Key key, this.i}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
'$i Page',
style: TextStyle(fontSize: 50.0),
),
),
);
}
}