Flutter Navigation (Tab Bar) and Select Drop Down form another page - android

I'm Developing Flutter Mobile Application. I want to Navigate another Page(With the Bottom Tab bar as display in the Picture) and I want to select a dropdown within the navigation's page. I think My problem is clear to you.
I Don't want to push that page.
And I don't want to duplicate My global Key
I added some screenshots of my app and numbers to understand you.

By Using a provider you can easily navigate between Navigation Tabs
Create a Provider for TabBar:
class MainTabProvider extends ChangeNotifier {
int _currentIndex = 0;
int get currentIndex {
return _currentIndex;
}
void setIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
Wrap you Tabbar with the Consumer
#override
Widget build(BuildContext context) {
return Consumer<MainTabProvider>(
builder: (context, data, child) => Scaffold(
backgroundColor: Colors.white,
body: _children[data.currentIndex],
......
Change Index from anywhere:
Provider.of<MainTabProvider>(context, listen: false).setIndex(2)

Related

Add new Text Field dynamically on Submit event

this is Antika. I have started learning to code since a few days back, and am only familiar with HTML/CSS/JS, and basics of dart/flutter
Developer Level: Beginner
Project type & language: I'm developing a Simple Notepad App, using flutter.
In my Project,
I want to dynamically add new TextField widgets on the screen, once the user hits enter or clicks the next button ('➡️'), in mobile devices, Just after the TextField in focus, and not to the end of the List.
Outline
User types text >> Clicks Submit     >> Keeping in mind TextField in focus >> Add another TextField just after this one.         >> The User feels like entering a new line.
For e.g., as is shown in the image below.
You could use a list with initially one TextField widget and onSubmitted adds another TextField to the list.
class MyWidget
extends StatefulWidget {
MyWidget({Key? key}) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
List<TextField> textFields = [];
#override
void initState(){
super.initState();
textFields.add(_buildTextField());
}
#override
Widget build(BuildContext context) {
return ListView(
children: textFields
);
}
TextField _buildTextField(){
return TextField(
autofocus: true,
onSubmitted: (_){
setState((){
textFields.add(_buildTextField());
});
}
);
}
}

How do I create a List of Widgets taking properties from multiple lists?

I want to create a list of widgets depending on the content of two or three dynamically generated lists.
List<String> Sound = ['A','B','C'];
List<String> Number = ['1','2','3'];
List<int> vertical = [10,20,30];
List<int> horizontal = [20,30,40];
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Row(
children: Sounds.map((sound) {
return FloatingActionButton(
onPressed: () => _audioCache.play(Sound),
child: Text(Number),
);
}).toList(),
),
),
);
}
}
Using the map function it seems like I can only build a list of Floating action buttons with one property. I want to give each button created by the map function properties from multiple different lists. How can I achieve that? This build function is in the state class of a stateful widget.
To expand on Uni's comment, here is a simple Dart program that shows the use of List.generate to create a list of Maps from two lists - your code would create your widgets:
void main() {
List<String> Sound = ['A', 'B', 'C'];
List<String> Number = ['1', '2', '3'];
var list = List.generate(
Sound.length,
(i) => {'Sound': Sound[i], 'Number': Number[i]},
);
print(list);
}
BTW it is recommended to name non-constant identifiers using lowerCamelCase, so Sound should be sound.
I would personally remodel the data.
If you are always using the same index of each list to build the widget why not make the a class with a sound and a number as properties then have one list of those objects.
Then the map you have would just be over those objects

Dynamic list of image in row with wrap (no space between) that allow for Long-pressing an image to open Edit options - Flutter

I'm receiving a list of images that I want to display dynamically in rows of 4 items each row. If there are 5 itens the row should wrap. The thing is, I need the images to allow for a longpress click that opens edit buttons in the appBar. Besides the edit button when longing pressing, it should allow for multiple selecting the other images.
Could this code be adapted for that:
class cardy extends StatefulWidget {
#override
_cardyState createState() => new _cardyState();
}
class _cardyState extends State<cardy> {
var isSelected = false;
var mycolor=Colors.white;
#override
Widget build(BuildContext context) {
return new Card(
color: mycolor,
child: new Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new ListTile(
selected: isSelected,
leading: const Icon(Icons.info),
title: new Text("Test"),
subtitle: new Text("Test Desc"),
trailing: new Text("3"),
onLongPress: toggleSelection // what should I put here,
)
]),
);
}
void toggleSelection() {
setState(() {
if (isSelected) {
mycolor=Colors.white;
isSelected = false;
} else {
mycolor=Colors.grey[300];
isSelected = true;
}
});
}
}
Yes, this code can be adapted for that ;)
To start, check out SliverGrid class.
https://api.flutter.dev/flutter/widgets/SliverGrid-class.html
Here is a (not complete) snippet to get you started, but you'll have to specify what options you want to use because this will not copy and paste solve your problem:
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 5,
crossAxisSpacing: 3,
crossAxisCount,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container()})),
I'll note that if you want to use the information you're gathering, namely which images you're selecting, do take care to store that information somewhere. That is, your example toggles selection for a single item, but how will you get that information later? That is, if you click 3 items then hit edit, you need a way to record which 3 items have been selected. One option is maintaining a list and .removing / .adding it as part of your toggle.

Flutter - How to stop re-rendering of ListView.builder after scrolling out of view

I'm building a Workout Tracker app using Flutter and Dart. On the tracking page are lists of exercises and a done Icon, when clicked, changes its color(To show that you're done with the set). Icon state changes locally in the file.
So the problem is when I scroll down, the upper items revert back to their original state. Long story short, I don't want the icons to Rerender on demand and save their state until I want to.
Tried AutomaticKeepAliveStateMixin but it doesn't seem to be working. I'm a newbie in coding so maybe I am implementing it wrong.
class _ExerciseInputState extends State<ExerciseInput>
with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
var deviceSize = MediaQuery.of(context).size;
return ListView.builder(
itemCount: widget.loadedRoutine.exercises.length,
itemBuilder: (BuildContext context, int i) {
return buildExerciseContainer(
widget.loadedRoutine.exercises[i].title,
widget.loadedRoutine.exercises[i].sets,
widget.loadedRoutine.exercises[i].reps,
deviceSize,
context);
},
);
}
}
No error messages.

Flutter GridView.builder how to update

I am trying to build an Flutter App with a GriView of cards and I want to add a new Card every time I hit the floatingActionButton. But how to update my view? I know the items are added to my list, but the GridView doesn't show the change.
List<Widget> cardsList = [];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Team Kitty'),
),
body: GridView.builder(
itemCount: cardsList.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Container(child: cardsList[index]);
}),
floatingActionButton: new FloatingActionButton(
onPressed: addCard(),
tooltip: 'Add Card',
child: new Icon(Icons.add),
),
);
}
addCard() {
setState(() {
cardsList.add(_RobotCard());
});
}
}
I find it hard to find good Grid documentation, maybe someone has a hint?
Thx Guys
You invoke addCard method while your widget is built instead of passing method's reference as onPressed parameter:
floatingActionButton: new FloatingActionButton(
onPressed: addCard, // pass method reference here
tooltip: 'Add Card',
child: new Icon(Icons.add),
)
Its too late to answer, but this might help someone who came here finding solution to similar problem .
The problem with this is , list will be updated with values , but builder doesn't rebuild the list immediately which is in visible region of the screen. If suppose you have a long list of cards , and if you add a new item to this list, then it wont be rebuild immediately . To see the change ,keep scrolling down the list and then come back up , then you can see that the builder has rebuild the list.
Hence to solve this issue after not finding any relevant answers, I tried this ,May be it might not be the best solution but it works .
The approach is, if you have a list
List CardList =List();
and it initially has 5 items. So builder would have build 5 cards on the screen.
Then , if a new 6th item is added , then even if you do
setState((){
CardList.add(newItem);
})
Builder won't rebuild immediately .
To solve this, use a variable of type Widget, and initialize with empty Text .
Widget WidgetToBeShownInBody = Text("");
Use this under scaffold , as shown :
#override Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Team Kitty'),
),
body: WidgetToBeShownInBody,
floatingActionButton: new FloatingActionButton(
onPressed: addCard(),
tooltip: 'Add Card',
child: new Icon(Icons.add),
),
);}
And Modify the onPressed function as this,
So, on every press of the button, empty text is shown in the scaffold for few milliseconds(which is negligible and goes unnoticed) and then the updated list of cards is shown on the screen.
addCard() {
//Show Empty Widget for few milliseconds
setState(() {
WidgetToBeShownInBody=Text("");
});
//update the list with new Item.
cardList.add(SomeNewItem);
//after some milliseconds ,
//use setState to update the variable to list of cards returned by GridViewBuilder
Timer(Duration(milliseconds: 50), () {
setState(() {
WidgetToBeShownInBody=GridView.builder(
itemCount: cardsList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Container(child: cardsList[index]);
});
});
});
}
The above code is kind of fooling the build function , that now UI only has a simple empty text.
But after few milliseconds , UI is rebuild-ed, as the setState updates the new value of variable "WidgetToBeShownInBody" with list of cards.
When a new item is added, show a empty widget instead of the builder for few milliseconds , and then after some millisecond delay , send the builder list with 6 items.
Hence builder rebuilds the UI with 6 items and "WidgetToBeShownInBody" is updated with new list of cards.
Hope this is clear and useful!!
If someone finds a proper solution for this , please do update .
Thanks!

Categories

Resources