I have a sign-up page which contains Text like privacy policy, terms and etc and I want that on clicking those text webpage should get open.
I used the GestureDetector for that but the issue is that it contains one child only
But I want all the three texts to be there and should perform Onclick or here onTap.
Any idea?
GestureDetector(
onTap: () => launch(
'https://docs.flutter.io/flutter/services/UrlLauncher- class.html'),
child: Text('Terms of use,',
style: TextStyle(
color: Colors.blueAccent,
fontSize: 18.0,
fontWeight: FontWeight.bold)),
)
expected: all three text with onTap inside GestureDetector.
actual: only one child is there.
You can try creating a Row widget which contains the text you need, that is, privacy policy, terms and etc, as its children. And then wrap the Text widgets with GestureDetector widgets. A code snippet is given below:
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: (){
print("Privacy policy");
},
child: Text("Privacy policy, "),
),
GestureDetector(
onTap: (){
print('Terms');
},
child: Text("Terms, "),
),
GestureDetector(
onTap: (){
print('Contact Us');
},
child: Text("Contact Us"),
),
],
),
),
Outputs:
Hope this helps!!
That's currently not directly supported by Flutter. But you can use RichText for implementing the requirement.
It is similar to Spannable string in Android.
Related
Flutter Web
So I have a button called add tags which opens up a modal. The Modal has only one text field and two buttons called add another tag and submit.
Now what I want to do is when the user clicks the add another tag button the app will generate another text field.
I've already seen some videos and read the documentation but since I need to work on a modal and the modal has defined size I'm not sure how to handle issues like
What happens if the user adds a lot of tags. How can I make the modal scrollable?
I'm new to flutter_form_builder so I'm not sure if the modal can handle it or not.
Here's my code:
final _formKey = GlobalKey<FormBuilderState>();
Future buildAddTagsForm(BuildContext context,
{Function()? notifyParent}) async {
return await showDialog(
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.5),
context: context,
builder: (context) {
var screen = MediaQuery.of(context).size;
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
content: SingleChildScrollView(
child: Container(
height: screen.height / 2,
width: screen.height > 650 ? 600.00 : screen.height * 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FormBuilder(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.cancel_presentation_rounded,
),
),
],
),
SizedBox(
height: 10,
),
FormBuilderTextField(
name: 'Tag Name',
decoration: InputDecoration(labelText: 'Tag name'),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MaterialButton(
color: CustomColors.buttonColor,
child: Text(
"Add another tag",
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {},
)
],
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MaterialButton(
color: CustomColors.buttonColor,
child: Text(
"Submit",
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {},
)
],
),
],
),
),
),
),
),
);
},
);
},
);
}
I'm assuming by "modal" we're talking about the AlertDialog here:
return AlertDialog(
content: SingleChildScrollView(
By using SingleChildScrollView as the AlertDialog content:, we can have any size / any number of text fields we like in the dialog. If their number are too many for the height of dialog inside our screen, the content will scroll.
Although, its immediate child Container with height prevents the SingleChildScrollView from doing its magic:
return AlertDialog(
content: SingleChildScrollView(
child: Container(
height: screen.height / 2,
I think the above AlertDialog would not scroll because it would never be big enough to need to scroll. Plus, any fields added that combine to be taller than that specified height (screen.height / 2) will cause an overflow warning and be cutoff visually.
So to answer question #1: "What happens if the user adds a lot of tags. How can I make the modal scrollable?"
using SingleChildScrollView is the right idea
lets swap the position of the Container with height and the SingleChildScrollView and this should allow the dialog to grow & scroll as needed as columns in FormBuilder increase
Your question #2: "I'm new to flutter_form_builder so I'm not sure if the modal can handle it or not."
flutter_form_builder shouldn't affect how SingleChildScrollView works
Example
Here's a partial example of an AlertDialog with scroll view content: that can grow in number.
Widget build(BuildContext context) {
return Container(
height: 300,
child: AlertDialog(
content: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: items,
),
),
),
actions: [
OutlinedButton(
child: Text('Add Row'),
onPressed: _incrementCounter
)
]
),
);
}
The complete example runnable in DartPard is here. (Add a 6 or 7 rows and then scroll the content.)
Warning
There's a gotcha with using the above AlertDialog inside a sized Container. That Container with height is not enough to constrain the AlertDialog size.
Your showDialog builder: (that pushes the AlertDialog into existence) must provide additional constraints in order for the sized Container to have constraints to size itself within. Without these constraints, the AlertDialog will grow until it matches the device viewport size. I believe this is a quirk with how showDialog is written, since I'm guessing it's a modal layer on top of the current stack of routes. (Someone can correct me if I'm wrong.) It's only constraint is the physical device, but nothing else. By wrapping builder:'s output with a constraining widget (such as Center) the output will be able to size itself.
To see this in action, remove the Center widget from the full example above an re-run it. The dialog will grow to fill the screen when adding rows instead of being at max 300px in height.
child: OutlinedButton(
child: Text('Open Dialog'),
onPressed: () => showDialog(
context: context,
builder: (context) => Center(child: MyDialog())
),
)
I'm currently trying to add the text ('Filter'), underneath an icon inside of the actions field within an AppBar.
Without any text being added underneath it. the action aligned exactly with the text and hamburger menu icon
Example:
There are two issues I'm having:
When I add text, the filter icon moves up a little, I want the icon to be the same spot but text added understand.
I'm getting an overflow issue
How can I fix this?
Thanks!
_appbarActions = [
Column(
children: [
IconButton(icon: const Icon(Icons.filter_alt_outlined), onPressed: () {}),
Text('Filter'),
],
)
];
Try the below snippet code:
To remove the space between IconButton and Text use Icon only;
For the overflow error you can manage the icon size with text fontSize (styles);
For events wrap the column by InkWell widget
Container(
margin: const EdgeInsets.only(right: 8.0),
child: InkWell(
onTap: () {},
child: Stack(
children: [
Center(
child: Icon(Icons.filter_alt_outlined),
),
Positioned(
child: Text(
'Filter',
style: TextStyle(fontSize: 10.0),
),
bottom: 5,
),
],
),
),
)
In my app users are required to submit their government ID's for verification to keep using the app. On the basis of the condition "isIDverified" it displays a text "Verified" or if it's under review it displays "Under Review". Inside the verified condition I want to put a popup which will say "Your account is under review" along with the text somewhere around this green empty block.
My code:
if (isIDVerified) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Verified',
style: kAppBarTitleTextStyle.copyWith(color: primaryColor),
),
SizedBox(
width: _screenUtil.setWidth(10),
),
Icon(
Icons.verified_user,
size: kPreferredIconSize,
color: Colors.green,
),
],
);
} else if (isIDUnderReview) {
return
Text(
'ID Under Review',
style: kAppBarTitleTextStyle.copyWith(color: primaryColor),
);
As far as I understand your question, I would like to answer it.
For displaying popups, you can make use of AlertDialogs.
You can do something like this.
void informUser() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Under Review"),
content: Column(
children: [ LIST OF WIDGETS ]
),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
You can put your widgets in the Column widget of AlertDialog's content.
staff.ulogin is a list returned from a web service. If there is more than one item returned, I need to display of list of those items (displaying the company name). I can get the first item displaying, but I'm not sure how to display the entire list.
I also need the user to be able to tap an item so I can setup that company for use, so I'll need to know what item they chose. Thanks for any help.
if (staff.ulogin.length > 1) {
Alert(
context: context,
title: 'Choose Company',
content: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//how to display all the items
ListTile(
title: Text(staff.ulogin[0].company),
onTap () {}, // <--- how to get the index of the item tapped
),
],
),
),
buttons: [
DialogButton(
child: Text('Cancel', style: TextStyle(color: Colors.white, fontSize: 20)),
color: kMainColor,
onPressed: () {
Navigator.of(context).pop();
},
),
],
).show();
} else
I believe that the correct way of display a list o items is using a ListView. For this case you can use a ListView.builder like this:
Container(
height: 300.0, // Change as you wish
width: 300.0, // Change as you wish
child: ListView.builder
(
itemCount: staff.ulogin.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(staff.ulogin[index].company),
onTap () {
someFunction(staff.ulogin[index]);
},
),
}
)
)
I have two rowCell's inside a Row widget in my app and I want to assign them different pages. I've tried putting the rowCell's in a GestureDetector, a FlatButton but neither of them have worked (as they should be linked to the Row widget and they need separate links for separate pages.)
Here is the part of my code:
...
new Divider(
height: _height / 20,
color: Colors.grey,
),
new Row(
children: <Widget>[
rowCell(10250, 'MEETUPS'),
rowCell(1520, 'FRIENDS'),
],
),
new Divider(height: _height / 20, color: Colors.grey),
...
Any solutions?
Just wrap the rowCell with GestureDetectorthen you will get separate onTap function with the same design.
Otherwise, you can use GestureDetector inside the rowCell(). And pass a function to the rowCell() to attach to the GestureDetector.
Widget rowSell(<your parameters>, Function onTapFunction) {
return GestureDetector(
onTap: onTapFunction,
child: <Your child>
),
}
And pass the function like:
new Row(
children: <Widget>[
rowCell(10250, 'MEETUPS', (){ <on Tap code> }),
rowCell(1520, 'FRIENDS', (){ <on Tap code> }),
],
),
The GestureDetector probably isn't working because you're wrapping it around the text and in that scenario, it's rare that it will work because you the onTap space is relative to space the text covers on the screen.
Try giving some padding inside the rowCell and then wrap it in a gesture detector, it will probably break your layout but at least you will know the problem and adjust accordingly.
Please try this...
If rowCell is return widget then wrap rowCell with GestureDetector and get click of that...
...
new Divider(
height: _height / 20,
color: Colors.grey,
),
new Row(
children: <Widget>[
GestureDetector(onTap: () {}, child: rowCell(10250, 'MEETUPS')),
GestureDetector(onTap: (){},child: rowCell(1520, 'FRIENDS')),
],
),
new Divider(height: _height / 20, color: Colors.grey),
...
From the comment from above you mention, I assume your rowCell function returns an Expanded widget.
So in rowCell function, inside Expanded widget add Inkwell widget. Also add one more argument which tells the page that you want to navigate to (onTap).
Widget rowCell(int count, String title, Widget navTo){
return Expanded(
child: Inkwell(
onTap: () => _navToPage(navTo)
child: .... //Your child widget
),
);
}
void _navToPage(Widget navTo){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => navTo,
),
);
}
new Divider(height: _height / 20, color: Colors.grey),
new Row(
children: <Widget>[
GestureDetector(onTap: () {}, child: rowCell(10250, 'MEETUPS', MeetupsPage())),
GestureDetector(onTap: (){},child: rowCell(1520, 'FRIENDS', FriendsListPage())),
],
),
new Divider(height: _height / 20, color: Colors.grey),