I need to go from first screen to second screen - android

I need to move from one screen to another. I made the transition from one class to another, but the main information of the second screen is indicated in the void main. How can I make the transition from one window to another without errors? So i need to transition from void main to void second. I'm sorry that my post has a lot of code, but help me please. Thanks in advance.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
enum GenderList {male, female}
class MyForm extends StatefulWidget {
#override
State<StatefulWidget> createState() => Registr();
}
class Registr extends State {
final _formKey = GlobalKey<FormState>();
GenderList _gender;
bool _agreement = false;
Widget build(BuildContext context) {
return Container(padding: EdgeInsets.all(10.0), child: new Form(key: _formKey, child: new Column(children: <Widget>[
new Text('Имя пользователя:', style: TextStyle(fontSize: 20.0),),
new TextFormField(validator: (value){
if (value.isEmpty) return 'Пожалуйста введите свое имя';
}),
new SizedBox(height: 20.0),
new Text('Контактный E-mail:', style: TextStyle(fontSize: 20.0),),
new TextFormField(validator: (value){
if (value.isEmpty) return 'Пожалуйста введите свой Email';
String p = "[a-zA-Z0-9+.\_\%-+]{1,256}#[a-zA-Z0-9][a-zA-Z0-9-]{0,64}(.[a-zA-Z0-9][a-zA-Z0-9-]{0,25})+";
RegExp regExp = new RegExp(p);
if (regExp.hasMatch(value)) return null;
return 'Это не E-mail';
}),
new SizedBox(height: 20.0),
new Text('Ваш пол:', style: TextStyle(fontSize: 20.0),),
Row(children: [Expanded(child:RadioListTile(
title: const Text('Мужской'),
value: GenderList.male,
groupValue: _gender,
onChanged: (GenderList value) {setState(() { _gender = value;});},
),
),
Expanded(child: RadioListTile(title: const Text('Женский'),
value: GenderList.female,
groupValue: _gender,
onChanged: (GenderList value ){setState(() {_gender=value;
});}))
],
),
Column(children: <Widget>[(SizedBox(height: 95.0)),
Align(alignment:Alignment.bottomCenter ,
child: CheckboxListTile(
value: _agreement,
title: new Text('Я ознакомлен'+(_gender==null?'(а)':_gender==GenderList.male?'':'а')+' с документом "Согласие на обработку персональных данных" и даю согласие на обработку моих персональных данных в соответствии с требованиями "Федерального закона О персональных данных № 152-ФЗ".'),
onChanged: (bool value) => setState(() => _agreement = value),
),
),
SizedBox(height: 20.0),
RaisedButton(onPressed: (){
if(_formKey.currentState.validate()) {
Color color = Colors.red;
String text;
if (_gender == null) text = 'Выберите свой пол';
else if (_agreement == false) text = 'Необходимо принять условия соглашения';
else {text = 'Форма успешно заполнена'; color = Colors.green;}
Scaffold.of(context).showSnackBar(SnackBar(content: Text(text), backgroundColor: color,));
Navigator.push(context, MaterialPageRoute(builder: (context) => MainScreen()));
}
}, child: Text('Проверить'), color: Colors.blue, textColor: Colors.white,),],)
],)));
}
}
class NewsBoxFavourit extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyFormState();
}
class MyFormState extends State {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
}
}
class NewsBox extends StatelessWidget {
String _imageurl;
NewsBox( {String imageurl,}) {
_imageurl = imageurl;
}
#override
Widget build(BuildContext context) {
if (_imageurl != null && _imageurl != '') return new Container(
color: Colors.black12,
height: 138.0,
child: Row(children: [
Image.network(_imageurl, width: 200.0, height: 150.0, fit: BoxFit.cover,),
Expanded(child: Container(padding: EdgeInsets.all(5.0), child: Column(children: [
Text('Дата'),
TextFormField(),
Text('Бег'),
TextFormField()
]
))
),
])
);
}
}
class NewsBoxFavourit2 extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyFormState2();
}
class MyFormState2 extends State {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
}
}
class NewsBox2 extends StatelessWidget {
String _imageurl2;
NewsBox2( {String imageurl2,}) {
_imageurl2 = imageurl2;
}
#override
Widget build(BuildContext context) {
Align(alignment: Alignment.topCenter,);
if (_imageurl2 != null && _imageurl2 != '') return new Container(
color: Colors.black12,
height: 200.0,
child: Row(children: [
Image.network(_imageurl2, width: 200.0, height: 150.0, fit: BoxFit.cover,),
Expanded(child: Container(padding: EdgeInsets.all(5.0), child: Column(children: [
Text('Дата'),
TextFormField(),
Text('Отжимания'),
TextFormField()
]
))
),
])
);
}
}
class NewsBoxFavourit3 extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyFormState3();
}
class MyFormState3 extends State {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
}
}
class NewsBox3 extends StatelessWidget {
String _imageurl3;
NewsBox3( {String imageurl3,}) {
_imageurl3 = imageurl3;
}
#override
Widget build(BuildContext context) {
if (_imageurl3 != null && _imageurl3 != '') return new Container(
color: Colors.black12,
height: 200.0,
child: Row(children: [
Image.network(_imageurl3, width: 200.0, height: 150.0, fit: BoxFit.cover,),
Expanded(child: Container(padding: EdgeInsets.all(5.0), child: Column(children: [
Text('Дата'),
TextFormField(),
Text('Пресс'),
TextFormField()
]
))
),
])
);
}
}
class NewsBoxFavourit4 extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyFormState4();
}
class MyFormState4 extends State {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
}
}
class NewsBox4 extends StatelessWidget {
String _imageurl4;
NewsBox4( {String imageurl4,}) {
_imageurl4 = imageurl4;
}
#override
Widget build(BuildContext context) {
if (_imageurl4 != null && _imageurl4 != '') return new Container(
color: Colors.black12,
height: 138.0,
child: Row(children: [
Image.network(_imageurl4, width: 200.0, height: 150.0, fit: BoxFit.cover,),
Expanded(child: Container(padding: EdgeInsets.all(5.0), child: Column(children: [
Text('Дата'),
TextFormField(),
Text('Приседания'),
TextFormField()
]
))
),
])
);
}
}
class MyFormState5 extends State {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
}
}
class NewsBox5 extends StatelessWidget {
String _imageurl5;
NewsBox5( {String imageurl5,}) {
_imageurl5 = imageurl5;
}
#override
Widget build(BuildContext context) {
Alignment.bottomCenter;
if (_imageurl5 != null && _imageurl5 != '') return new Container(
color: Colors.black12,
height: 138.0,
child: Row(children: [
Image.network(_imageurl5, width: 200.0, height: 150.0, fit: BoxFit.cover,),
Expanded(child: Container(padding: EdgeInsets.all(30.0), child: Column(children: [
Text('Дата'),
TextFormField(),
Text('Прыжки'),
TextFormField()
]
))
),
])
);
}
}
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {return SizedBox(width: 100 , height: 80,
child:
RaisedButton(onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => SecondScreen()));
}, child: Text('Сформировать результаты')))
;
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {return SizedBox(width: 200 , height: 100,
child:
Scaffold(
appBar: AppBar(title: Text('Результаты')),
body: Center(child: RaisedButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Назад'))),
));
}
}
void main() => runApp(MaterialApp(debugShowCheckedModeBanner: false,
home: Scaffold(appBar: PreferredSize(preferredSize: Size.fromHeight(30.0),
child: AppBar(centerTitle:true, title: Text('Форма ввода'),),),
body: MyForm(),),),);
void second() => runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
body:
ListView(children: [
NewsBox(
imageurl: 'https://img.rl0.ru/0e5dfa5a89802f6ae40eea1312ee89c0/c615x400i/https/news.rambler.ru/img/2019/01/25160023.223341.8124.jpeg'),
NewsBox2(imageurl2: 'https://avatars.mds.yandex.net/get-zen_doc/1873797/pub_5e3d7968f58c3b19c8d9605e_5e40115dc0c2cd2f40ec8403/scale_1200'),
NewsBox3(imageurl3: 'https://www.bodybuilding.com/images/2018/april/the-best-ab-workout-for-a-six-pack-header.jpg'),
NewsBox4(imageurl4: 'http://vlzsport.ru/wp-content/uploads/prisedanie.png'),
NewsBox4(imageurl4: 'http://vlzsport.ru/wp-content/uploads/prisedanie.png'),
MainScreen()
],) ,
drawer: Drawer(child: ListView(
children: <Widget>[SizedBox(height: 0,),
Align(alignment: Alignment.bottomLeft,),
DrawerHeader(child: new Text("Меню"),
decoration: BoxDecoration (
color: Colors.blueAccent), ),
SizedBox(height: 10,),
Align(alignment: Alignment.topLeft,),
ListTile(
title: Text("Программа"),
trailing: Icon(Icons.arrow_forward_ios),
),
ListTile(
title: Text("Настройки"),
trailing: Icon(Icons.arrow_back_ios),
),
ListTile(title: Text('Результаты'),
trailing: Icon(Icons.arrow_back_ios,),
),
],
),),
)
)
);

You should have runApp() only once , to return a widget that will be the entry point for your app. After that you can go from one screen to another using Navigator.push() .
Please refer to this link that explains everything in detail :
https://flutter.dev/docs/cookbook/navigation/navigation-basics

I didn't actually went through your code because it is too bloated with irrelevant content. However, to pass data between one screen to another and vice-versa you just need to:
final bar = await Navigator.pushNamed(MyScreen2, arguments: foo);
Now on the MyScreen2 you can get your data on didChangeDependencies for example as such:
final data = ModalRoute.of(context).settings.arguments;
If you want to pass back data from MyScreen2 to the previous one when the route is popped, just do Navigator.pop(context, data); and that data will be assigned to the bar property above.

Related

How can I change the text color inside the chat bubble?

While I am typing the message it encodes it into white but when I have sent it, it turns to black which is the same with the response that I have been receiving. Kindly help me how will i change it to white.
import 'package:dialog_flowtter/dialog_flowtter.dart';
import 'package:flutter/material.dart';
import 'Messages.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'QuickTropa',
theme: ThemeData(
primaryColor: Color(0XFFf7c59f),
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
late DialogFlowtter dialogFlowtter;
final TextEditingController _controller = TextEditingController();
List<Map<String, dynamic>> messages = [];
#override
void initState() {
DialogFlowtter.fromFile().then((instance) => dialogFlowtter = instance);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('QuickTropa'),
backgroundColor: Color(0XFF087830),
),
body: Container(
child: Column(
children: [
Expanded(child:
MessagesScreen(
messages:
messages)),
Container(
padding: EdgeInsets.symmetric(
horizontal: 14,
vertical: 8
),
color: Color(0XFF087830),
child: Row(
children: [
Expanded(child:
TextField(
controller: _controller,
style: TextStyle(color: Colors.white),
)),
IconButton(
onPressed: () {
sendMessage(_controller.text);
_controller.clear();
},
color: Colors.white ,
icon: Icon(Icons.send))
],
),
)
],
),
),
);
}
sendMessage(String text) async {
if (text.isEmpty) {
print('Message is empty');
} else {
setState(() {
addMessage(Message(
text: DialogText(text: [text])), true);
});
DetectIntentResponse response = await dialogFlowtter.detectIntent(
queryInput: QueryInput(text: TextInput(text: text)));
if (response.message == null) return;
setState(() {
addMessage(response.message!);
});
}
}
addMessage(Message message, [bool isUserMessage = false]) {
messages.add({
'message': message,
'isUserMessage': isUserMessage
});
}
}
import 'package:dialog_flowtter/dialog_flowtter.dart';
import 'package:flutter/material.dart';
class MessagesScreen extends StatefulWidget {
final List messages;
const MessagesScreen({Key? key, required this.messages}) : super(key: key);
#override
State<MessagesScreen> createState() => _MessagesScreenState();
}
class _MessagesState extends State<MessagesScreen> {
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class _MessagesScreenState extends State<MessagesScreen> {
#override
Widget build(BuildContext context) {
var w = MediaQuery.of(context).size.width;
return ListView.separated(
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: widget.messages[index]['isUserMessage']
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 14),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(
20,
),
topRight: Radius.circular(20),
bottomRight: Radius.circular(
widget.messages[index]['isUserMessage'] ? 0 : 20),
topLeft: Radius.circular(
widget.messages[index]['isUserMessage'] ? 20 : 0),
),
color: widget.messages[index]['isUserMessage']
? Color(0XFF087830)
: Color(0XFF087830).withOpacity(0.8)),
constraints: BoxConstraints(maxWidth: w * 2 / 3),
child:
Text(widget.messages[index]['message'].text.text[0])),
],
),
);
},
separatorBuilder: (_, i) => Padding(padding: EdgeInsets.only(top: 10)),
itemCount: widget.messages.length);
}
}
I tried putting Color:Colors.white isnide the box decoration but of course it wouldn't let me. I can't think anymore where to put it.
Try this
Text(widget.messages[index]['message'].text.text[0],
style:TextStyle(color:Colors.white,)
)

cannot pass value from one class to another

I have two classes.First class consist of list from the firestore. I want to pass value from first class to second class. I did create a constructor in the second class to get the value from the first class but i am getting null value in second class. I want to pass value of snap[index]['url'] to another class which has constructor url.
*first class*
Widget _html() {
return Column(
children: [
const Text("\nWorship"),
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("Worship").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if(snapshot.hasData) {
final snap = snapshot.data!.docs;
return ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: snap.length,
itemBuilder: (context, index) {
return Stack(
children: [
GestureDetector(
child:Container(
height:50,
width: MediaQuery.of(context).size.width,
child: Card(
child: Center(
child: Row (
children : [
Text(
snap[index]['name'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(width:50),
Text(
snap[index]['title'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
]
)),
)),
onTap: () {
var ur= snap[index]['url'];
print( ur );
**DashBoards(url: ur);** //value to be passed
},
)
],
// ),
);
},
);
} else {
return const SizedBox();
}
},
)
],
);
}
heres my second class
class DashBoards extends StatefulWidget {
final String url;
const DashBoards({Key? key,required this.url}) : super(key: key);
#override
_DashBoardsState createState() => _DashBoardsState(url);
}
class _DashBoardsState extends State<DashBoards> {
late final String url;
_DashBoardsState(url);
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
//backgroundColor: Colors.white60,
endDrawerEnableOpenDragGesture: false,
appBar: AppBar(
backgroundColor: Colors.green,
),
body: WebViewPlus (
initialUrl: url,
),
);
}
}
You can access the value by using the widget.
Example:
///First Class
class FirstClass extends StatefulWidget {
const FirstClass({Key? key}) : super(key: key);
#override
State<FirstClass> createState() => _FirstClassState();
}
class _FirstClassState extends State<FirstClass> {
#override
Widget build(BuildContext context) {
return SecondClass(url: "https://www.google.com/");
}
}
///Second class
class SecondClass extends StatefulWidget {
final String url;
const SecondClass({Key? key, required this.url}) : super(key: key);
#override
State<SecondClass> createState() => _SecondClassState();
}
class _SecondClassState extends State<SecondClass> {
#override
Widget build(BuildContext context) {
///Access the value by using widget
return Text(widget.url);
}
}
*first class*
Widget _html() {
return Column(
children: [
const Text("\nWorship"),
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("Worship").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if(snapshot.hasData) {
final snap = snapshot.data!.docs;
return ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: snap.length,
itemBuilder: (context, index) {
return Stack(
children: [
GestureDetector(
child:Container(
height:50,
width: MediaQuery.of(context).size.width,
child: Card(
child: Center(
child: Row (
children : [
Text(
snap[index]['name'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(width:50),
Text(
snap[index]['title'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
]
)),
)),
onTap: () {
var ur= snap[index]['url'];
print( ur );
**DashBoards("your value");** //value to be passed
},
)
],
// ),
);
},
);
} else {
return const SizedBox();
}
},
)
],
);
}
heres my second class
class DashBoards extends StatefulWidget {
final String url;
DashBoards(this.url);
#override
_DashBoardsState createState() => _DashBoardsState(url);
}
class _DashBoardsState extends State<DashBoards> {
late final String url;
_DashBoardsState(url);
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
//backgroundColor: Colors.white60,
endDrawerEnableOpenDragGesture: false,
appBar: AppBar(
backgroundColor: Colors.green,
),
body: WebViewPlus (
initialUrl: widget.url,
),
);
}
}

Flutter: ListView disposes widgets when keyboard pops up

I have an app with a page that has a ListView.builder().
Each row of the list is a stateful widget (match_chat_row.dart).
When you click on that stateful widget, it's navigating to another stateful widget (chat_screen.dart).
chat_screen.dart has a TextField.
The problem is that last few widgets(match_chat_row.dart) of the ListView are being disposed when the keyboard pops up on one of the first match_chat_row's chat_screen.dart.
I made this simple app to demonstrate it:
main.dart
import 'package:flutter/material.dart';
import 'match_chat_row.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#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, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final String _pageName = "Screen";
List<String> _chats = ["A","B","C","D","E","F","G","H","I","J"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _body()
);
}
_body(){
return ListView.builder(
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
);
}
Widget _buildRow(String chat) {
return
Column(
key: ValueKey<String>('chat-$chat'),
children: [
Center(
child:
MatchChatRow(
content: chat,
),
),
Divider(color: Colors.grey.withOpacity(0.20), thickness: 0.8, height: 0.0,)
],
);
}
}
match_chat_row.dart
import 'package:flutter/material.dart';
import 'chat_screen.dart';
class MatchChatRow extends StatefulWidget {
final String content;
const MatchChatRow({required this.content});
#override
_MatchChatRowState createState() => _MatchChatRowState();
}
class _MatchChatRowState extends State<MatchChatRow> {
#override
void dispose(){
print("Disposed ROW! ${widget.content}");
super.dispose();
}
#override
Widget build(BuildContext context) {
final rowHeight = 100.0;
final rowPadding = 10.0;
return
InkWell(
onTap: () =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
key: ValueKey(widget.content),
),
),
),
child:
Container(
height: rowHeight,
padding: EdgeInsets.all(rowPadding),
child: Row(
children: <Widget>[
SizedBox(
width: 20.0,
),
Expanded(
child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.content),
Text("_buildSubtitle()"),
],
)
),
],
),
)
);
}
}
chat_screen.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({required Key key,}): super(key: key);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final TextEditingController _messageController = TextEditingController();
bool _isComposingMessage = false;
bool _isChatExist = false;
bool _isLoading = false;
bool _isSending = false;
#override
void initState() {
super.initState();
}
#override
void dispose(){
print("disposed chat! ${widget.key}");
super.dispose();
}
Container _buildMessageTF() {
return Container(
margin: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
decoration: BoxDecoration(
border:
Border.all(color: Theme.of(context).accentColor.withOpacity(0.3)),
borderRadius: BorderRadius.circular(30)),
child: Row(
children: <Widget>[
Expanded(
child:
TextField(
minLines: 1,
maxLines: 4,
controller: _messageController,
textCapitalization: TextCapitalization.sentences,
onChanged: (messageText) {
setState(() => _isComposingMessage = messageText.isNotEmpty);
},
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
hintText: 'Message...'),
),
),
],
),
);
}
#override
Widget build(BuildContext context) {
return
WillPopScope(
onWillPop: () {
return Future.value(true);
},
child:
SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Hi")
),
body:
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (!_isChatExist && !_isLoading) SizedBox.shrink(),
_buildMessageTF(),
],
),
),
),
)
);
}
}
And whenever I click on the TextField and the Keyboard pops up the below widgets are being disposed (this is my debug console):
I/flutter (23372): Disposed ROW! I
I/flutter (23372): Disposed ROW! J
I/flutter (23372): Disposed ROW! H
update your _body from main
_body(){
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
),
);
}

How to Create a List of Categories using Containers

so i wanted to create a list of categories (Day-Week-Month) and i achieved it just fine using a
listView.builder but it isn't centered on the horizontal axis so i had the idea to do it with containers.
https://im3.ezgif.com/tmp/ezgif-3-aba2cbc290ae.gif
so using only containers as the gif shows when i press it stays active even if i press on another one
which is something i dont want obviously.
https://im3.ezgif.com/tmp/ezgif-3-e1e304256aaf.gif
my code :
class DWM extends StatefulWidget {
#override
_DWMState createState() => _DWMState();
}
class _DWMState extends State<DWM> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TextDWM(
text: "Day",
),
TextDWM(
text: "Week",
),
TextDWM(
text: "Month",
),
],
),
);
}
}
class TextDWM extends StatefulWidget {
final String text;
bool isActive;
TextDWM({this.text,this.isActive = false});
#override
_TextDWMState createState() => _TextDWMState();
}
class _TextDWMState extends State<TextDWM> {
#override
Widget build(BuildContext context) {
return Column(
children: [
GestureDetector(
onTap: (){
setState(() {
widget.isActive = true;
});
},
child: Text(
widget.text,
style: TextStyle(
color: widget.isActive ? Colors.white : Colors.grey,
),
),
),
SizedBox(height: 5,),
Container(
height: 2,
width: 40,
color: widget.isActive ? Colors.deepOrange : Colors.transparent,
)
],
);
}
}
Please check out the code below to learn one of the ways this could be done. However it is advisable to use something like Inherited widget or Provider to pass data down the widget tree.
import 'package:flutter/material.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
home: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter Demo"),
),
body: DWM(),
);
}
}
class DWM extends StatefulWidget {
#override
_DWMState createState() => _DWMState();
}
class _DWMState extends State<DWM> {
final List<String> _items = ["Day", "Week", "Month"];
List<bool> _active = []; //[true,false,false];
#override
void initState() {
super.initState();
_active = List.filled(_items.length, false);
}
void setActive(int active) {
setState(() {
_active = List.filled(_items.length, false);
_active[active] = true;
});
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(
_items.length,
(index) => TextDWM(
text: _items[index],
isActive: _active[index],
setActive: () => setActive(index),
),
),
),
);
}
}
class TextDWM extends StatelessWidget {
final String text;
final bool isActive;
final Function setActive;
const TextDWM({this.text, this.isActive, this.setActive});
#override
Widget build(BuildContext context) {
return Column(
children: [
GestureDetector(
onTap: () {
setActive();
},
child: Text(
text,
style: TextStyle(
color: isActive ? Colors.white : Colors.grey,
),
),
),
const SizedBox(
height: 5,
),
Container(
height: 2,
width: 40,
color: isActive ? Colors.deepOrange : Colors.transparent,
)
],
);
}
}

TextEditingController makes widget lose its previous state

When I use TextEditingController in CupertinoTextField, and change to another widget(page) and return, the previous state in that page is lost.
When I uncomment //controller: textController, everything works fine.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: DefaultTabController(
length: 2,
child: Scaffold(
body: TabBarView(
children: [new Search(), new Setting(),
],
),
bottomNavigationBar: Container(
height: 60,
child: new TabBar(
tabs: [
Tab(icon: new Icon(Icons.search)),
Tab(icon: new Icon(Icons.settings)),
],
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
),
)
),
),
);
}
}
class Setting extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.check),
onPressed: () {
Navigator.push(context, CupertinoPageRoute(
builder: (context) =>
new Scaffold(
appBar: AppBar(title: Text('3'),),
)));
});
}
}
class Search extends StatefulWidget {
#override
createState() => new SearchState();
}
class SearchState extends State<Search> {
String currentWord = '';
final TextEditingController textController = new TextEditingController();
#override
void dispose() {
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Row(
children: <Widget>[
new Expanded(
child: new CupertinoTextField(
style: TextStyle(color: Colors.white),
cursorColor: Colors.white,
//controller: textController,
maxLines: 1,
clearButtonMode: OverlayVisibilityMode.editing,
onChanged: (text) {
setState(() {
currentWord = text;
});
},
),
),
],
),
),
body: ListView.builder(
itemCount: 5,
itemBuilder: (context, i) {
return Text(currentWord);
})
);
}
}
The expected result(without controller set):get back and the state keeps the same.
Actual results(with controller set): get back and the state lost
The explanation for the observed behavior is the following:
CupertinoTextField uses an internal TextEditingController for which the framework automatically sets an AutomaticKeepAlive. This keepAlive is responsible for keeping the state.
If you use your own controller, you are in charge of attaching the AutomaticKeepAlive because the framework doesn't do it for you.
The following snippet adds the keepAlive to your code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: DefaultTabController(
length: 2,
child: Scaffold(
body: TabBarView(
children: [
new Search(),
new Setting(),
],
),
bottomNavigationBar: Container(
height: 60,
child: new TabBar(
tabs: [
Tab(icon: new Icon(Icons.search)),
Tab(icon: new Icon(Icons.settings)),
],
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
),
)),
),
);
}
}
class Setting extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.check),
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => new Scaffold(
appBar: AppBar(
title: Text('3'),
),
)));
});
}
}
class Search extends StatefulWidget {
#override
createState() => new SearchState();
}
class SearchState extends State<Search> with AutomaticKeepAliveClientMixin {
String currentWord = '';
final TextEditingController textController = new TextEditingController();
#override
void initState() {
super.initState();
textController?.addListener(updateKeepAlive);
}
#override
void dispose() {
textController?.removeListener(updateKeepAlive);
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
super.build(context); // See AutomaticKeepAliveClientMixin.
return new Scaffold(
appBar: new AppBar(
title: new Row(
children: <Widget>[
new Expanded(
child: new CupertinoTextField(
style: TextStyle(color: Colors.white),
cursorColor: Colors.white,
controller: textController,
maxLines: 1,
clearButtonMode: OverlayVisibilityMode.editing,
onChanged: (text) {
setState(() {
currentWord = text;
});
},
),
),
],
),
),
body: ListView.builder(
itemCount: 5,
itemBuilder: (context, i) {
return Text(currentWord);
}));
}
#override
bool get wantKeepAlive => textController?.text?.isNotEmpty == true;
}

Categories

Resources