How to prevent selectedItemBuilder from moving text up - flutter

Using a DropdownButton, I need the selected item to be a different color than the list of items in the dropdown menu that appears when you tap the button. According to the Flutter documentation, I should use selectedItemBuilder. As can be seen right there in the example within the documentation, using the selectedItemBuilder results with the selected text being shifted up which does not look good.
How can I get the selected item to be down in line with the drop-down icon where it is supposed to be while having separate colors for the menu items and the selected item?

I found that this is an open issue on GitHub. A work around is to wrap the widget returned by the builder (and also the hint if you have one) in a Center widget.
DropdownButton<String>(
selectedItemBuilder: (_) {
return items.map<Widget>((String item) {
return Center(
child: Text(item),
);
}).toList();
},
hint: Center(child: myHintWidget),
...

Related

I want to make my Icons Automatically go to next Row in flutter if previous row gets completrly filled with icons

I am building a quiz app using Dart flutter in that some questions will get displayed and users have to click on true or false buttons depending upon question is right or wrong. To tell users that they are right or wrong icon (✓ or ✘) will get displayed in bottom row every time they choose answer by clicking on either of the button. But in flutter if row gets completely filled i got error
value: Not in inclusive range. So i want that icon should automatically go to next row.
Heres the short code which i tried:
List scorekeeper = [];
void score(bool userpickedanswer) {
setState((){
if (userpickedanswer == correctanswer) {
scorekeeper.add(Icon(Icons.check, color: Colors.green,));
}
else {
scorekeeper.add(Icon(Icons.close, color: Colors.red,));
}
}
Row {
childeren : scorekeeper
You can use the Wrap widget instead of the Row widget and when the line of icon fills to the end the Wrap widget makes another line automatically
Use the code like this:
Wrap(
children: scorekeeper,
),
You can use a wrap instead of a row. It prevents overflow by displaying the items depending on the available space:
https://api.flutter.dev/flutter/widgets/Wrap-class.html

SliverList setState to Affect Only Selected Item Flutter

I have a button on every item on my SliverList. When I click a specific list item button, I wish it change to a different widget by using setState. Only that specific item button should change to a different widget while the rest on the list retains its own item button.
Example below. The problem of course is that when I click any button on the list, all buttons on every item on the list changes. What is needed so that it affects only the specific item on the list whose button was pressed?
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
final item = gd[index];
return Container(
child: Column(
children: [
item.mypicwidget(context,item.pid),
_shownewwidget
? item.newwidget(context)
: RaisedButton(
onPressed: () {
setState(() {
_shownewwidget=true;
});
},
child: const Text('Press Me'),
),
]
),
);
Figured this out.
I believe the approach is to add to the existing list an object key to represent whether widget1 or widget2 to render, eg. tag: 'normal' or tag: 'clicked'. Depending on index.tag, either widget1 or widget2 will be displayed. So for a widget with a button wherein the tag is normal, the button will have a function when clicked changes the index.tag of the item from normal to clicked. When the Sliverlist sees this new value, it automatically renders the corresponding widget.

How to set a widget as a button in Flutter

I set two widgets in a Stack(), the one in the back is a sidebar and the one in the front is my main page.
When I click on the menu button from the main page, the main page gets shifted to the right and then the user can see the sidebar.
Now the problem is when the sidebar gets displyed i'm obliged to click exactly on the menu button to go back to the main page.
What i want to do is just to click anywhere in the main page to hide the sidebar.
I mean that i want to set the whole main page as a button when the sidebar is displayed.
You can use InkWell
InkWell(
onTap: (){
/// do something
},
child: Text('data') /// your widget,
),
You can also use GestureDetector
Generally if you want to make anything tappable you can just wrap the widget with GestureDetector
I fixed it by wrapping the main page with InkWell() and I added this to the onTap property"
InkWell(
onTap: isSidebarCollapsed ? () {
setState(() {
isSidebarCollapsed = false;
});
} : null,
child: Container(...)
)
Note that isSidebarCollapsed is the variable that determines if the menu is displayed or not.
Explaination of the code:
If the sidebar is collapsed (is displayed) then the onTap property returns a function where I set the variable isSidebarCollapsed to false (to say that the sidebar is gonna be hidden).
Else it returns null

How to programmatically call multiple widget under a stack in flutter

I've a screen with several buttons and I would like to show a sliding panel for each button (passing some information to show in the panel).
I've used this widget:
https://pub.dev/packages/sliding_up_panel
I would like to understand how I can show a widget that is under a Stack passing programmatically some information once I click on a specific button.
It is possible?
Following a brief snipped of code in which we can see the Stack that contains the SlidingPanel. I would like to be able to show the Sliding panel clicking on a specific button and passing an information to it programmatically.
The only solution that I've found up to now is adding all the possible sliding panel to the Stack and then based on the click on the button showing only the one I need, but I hope there is a better way to do this.
Thank you
return Stack(
children: [
Scaffold(
.....
),
SlidingUpPanel(
panelController: panelController,
nameTEController: nameTEPanel,
platform: 'Instagram',
)
]
Just populate your list of Widgets inside a List. If you are using a StatefullWidget, then just call setState(() => )
You could do something like this:
List<Widget> _myWidgetList = [];
[...]
return Stack(
children: _myWidgetList);
List<Widget> _buildMyWidgetList() {
final List<Widget> tmpList = [];
tmpList..add(Widget1)
..add(Widget2);
setState(() => _myWidgetList = tmp);
}
Then just call your buildWidgets functions on the Buttons.
Another way would be to use Bloc: https://pub.dev/packages/flutter_bloc

Flutter toggle Radio widget

I'm using Radio widgets to set the user gender. These Radio button widgets are designed very well to handle the selection changes act accordingly, but I does not find a solution to somehow deselect one already selected option. I would like the gender radio group to be optional. But after user selects let's say female, he/she can change the selection to male, but can't deselect the female/male option. (So that none of the option is selected.)
There is only an onChanged property and it only changes if the gender changes. No such thing like onTap or something similar. So no matter if I check that gender if it's the same, onChanged won't be called.
For that reason I tried to use a GestureDetector which should solve this issue (with this I should be able to deselect the already selected option) but in case of radio widgets it does not work. I also tried to change it's behavior property but it did not help either.
Here is the function which I use to create gender radio option with a text in a Row.
Widget _buildRadioWithText(final genderChangeNotifier, final Gender genderParam, final String genderText) {
return Row(
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
child: Radio<Gender>(
visualDensity: VisualDensity.compact,
value: genderParam,
groupValue: genderChangeNotifier.gender,
onChanged: (Gender gender) {
genderChangeNotifier.gender = gender;
print(gender.toString());
},
),
onTap: () {
if (genderChangeNotifier.gender == genderParam) {
genderChangeNotifier.gender = Gender.NA;
print("Not answered!");
}
},
),
GestureDetector(
onTap: () {
if (genderChangeNotifier.gender == genderParam) {
genderChangeNotifier.gender = Gender.NA;
print("Not answered!");
} else {
genderChangeNotifier.gender = genderParam;
print(genderParam.toString());
}
},
child: Text(
genderText,
style: TextStyle(
fontSize: _fontSize,
),
),
),
],
);
}
Function call:
_buildRadioWithText(genderChangeNotifier, Gender.FEMALE, "Female"),
_buildRadioWithText(genderChangeNotifier, Gender.MALE, "Male"),
genderChangeNotifieris just a provider to set and get the Gender value and notify listeners when a Gender is set.
final GenderNotifier genderChangeNotifier= Provider.of<GenderNotifier>(context);
GestureDetector's onTap works well when I tap on the Text widget. It selects then deselects the option just as I'd like to but in case of the Radio widget onTap is never called.
Any idea how to achieve the deselection when I tap/click on the Radio widget itself? And why the GestureDetector that wraps the Radio does not register the tap events?
The GestureDetector's onTap is not being called because the GestureDetector inside the Radio widget is taking priority. By default, when two GestureDetectors are competing for input, only one will "win". In this case, the winner is the one in the Radio. This article discusses "GestureArenas" and how you can allow both GestureDetectors to process input.
However, consider whether allowing the user to deselect the radio button is the correct solution. Radio buttons are designed not to be deselected once the user has selected an option. You might instead:
Offer a third, "I'd rather not say" option
Use toggleable buttons instead of a radio group
Use a dropdown menu instead of a radio group
See this answer for more info on the usability aspect of this.