How can I place some buttons to separate between tabs in a sliding up panel? Currently what I am trying to do is place them only when the slider is opened up, ohterwise the button tabs should dissapear. I am trying to controll this behavior with ternary operator and the variable:
PanelState == PanelState.OPEN ?
but it does not work for me. The row dissapear when I close the panel.
SlidingUpPanel(
body: Body()
backdropEnabled: true,
panelSnapping: true,
collapsed: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
_pcBreedsGrouping.open();
},
child: const Text(
'Breeds',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
InkWell(
onTap: () {
_pcBreedsGrouping.open();
},
child: const Icon(
Icons.arrow_drop_down,
color: Colors.black,
size: 30,
),
),
],
),
),
minHeight: MediaQuery.of(context).size.height * 0.08,
controller: _pcBreedsGrouping,
defaultPanelState: PanelState.CLOSED,
panel: Positioned(
child: Stack(
children: [
PanelState == PanelState.OPEN
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Breeds',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),
),
InkWell(
onTap: () => _pcBreedsGrouping.close(),
child: const Icon(
Icons.arrow_drop_up,
color: Colors.black,
size: 30,
),
),
],
)
: Container(),
Visually, the panel is like this right now and I drawed what I am trying in red:
When I close the panel I would like it to be how it is right now, without the buttons, but I do not know how to make them dissapear when is closed:
What I am trying to accomplish:
Related
I recently picked up Flutter and Dart and am attempting to create an app that has a modal with three parts: a header, actual content, and a footer.
For the header I am looking to add a title (Text) center aligned and a close button right aligned.
I have the following code:
Column(
children: [
Row(
children: [
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),
],
),
)
Visually, this looks like so:
At a glance this looks fine but if you stare at it for a bit it doesn't. The "Filters" title isn't actually centered because (I assume) of the width of the X-button. I am struggling to figure out how to deal with this.
What is the proper way to solve this?
You can add empty SizedBox with width as much as IconButton takes, try this:
Row(
children: [
SizedBox(
width: width: 24 +
8 +
8, // the default size of icon + two default horizontal padding for IconButton
),
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),
or you can add on other IconButton with opacity 0 to hide the button and make title center, like this:
Row(
children: [
Opacity(
opacity: 0,
child: IconButton(
icon: const Icon(Icons.close),
onPressed: () {},
),
),
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),
I have a widget that builds a list from an array. Each item in the array builds a widget with some columns and rows. I want the text to break so It doesnt overflow.
I've tried adding overflow: TextOverflow.ellipsis to the Text or wrapping the Row that wraps the icon and the text that overflow with a Expanded widget, but both didn't work.
Actually it looks like this:
This is my code:
child: Column(
verticalDirection: VerticalDirection.down,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: < Widget > [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: < Widget > [
Row(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: < Widget > [
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
setState(() {
entries[index].pilldone = !entries[index].pillDone;
});
},
tooltip:
entries[index].pillDone ? 'Tomada' : 'No tomada',
backgroundColor: entries[index].pillDone ?
Colors.green :
Theme.of(context).primaryColor,
child: const Icon(Icons.check),
),
),
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
showAdaptiveActionSheet(
context: context,
cancelAction: CancelAction(
title: const Text('Cancelar'),
),
actions: < BottomSheetAction > [
BottomSheetAction(
title: const Text('Modificar'),
onPressed: () {}),
BottomSheetAction(
title: const Text('Eliminar'),
onPressed: () {
Navigator.pop(context);
_askRemovePill(entries[index].iD);
}),
]);
},
tooltip: 'Eliminar',
backgroundColor: Colors.blue,
child: const Icon(Icons.mode_edit),
)),
],
),
],
),
In your case, all you need to do is wrap your Text inside the Row with an Expanded widget
Expanded(
child: Text(/*......your text widget........*/),
),
The Expanded widget gives your Text widget horizontal constraints
IF you don't wish to see the text go on to the next line,
use the overflow property on the text
overflow : TextOverflow.ellipsis, //inside Text
Use the Wrap widget instead of the Row widget. It will break the text to the next line should there be an overflow.
Like this,
Wrap(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),
I have a problem, it's not difficult, but I can't solve it. I have a task book program. At the top is the word "task", this word is in the middle as needed. But there is also a button (add). The problem is that I can't put it closer to the center, to the word "task"! I'll be grateful if someone can help me move this button to the center to the level of the word "task"
My code :
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 3,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 40.0),
child: Text(("Tasks"),
style: TextStyle(fontSize: 70.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
)
),
Expanded(
child: FlatButton(
textColor: Colors.black,
color: Colors.white12,
child: Text('+',style: TextStyle(fontSize: 70.0,
color: Colors.black,
)),
onPressed: () {
if (textController.text.isNotEmpty) {
WidgetList.add(
new ListItem(textController.text, false));
setState(() {
valText = true;
textController.clear();
});
}
else
{
setState(() {
valText = false;
});
}
},
padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),)
],
),
),
Try to not use FlatButton cause' it is deprecated, and as you use an icon to create a button, use IconButton instead :
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, // this is to center both
children: <Widget>[
const Text(
"Tasks",
style: TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
IconButton(
color: Colors.black,
iconSize: 28,
constraints: const BoxConstraints(),
padding: EdgeInsets.zero,
icon: const Icon(Icons.add_outlined),
onPressed: () {},
)
],
),
),
Ok, the contraints in the IconButton, in less words it helps you to be close between the Text and the Icon and delete the padding (but not all), aaaand if you add padding: EdgeInsets.zero, literally it deletes all the padding to zero. Try to add some padding, to fix the "closer"
I am trying to create a row widget with two texts widgets inside, however the text keeps overflowing out of screen instead of going right under it. Why is this happening and how can I avoid this?
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 40.0),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/main_cover.jpg"),
fit: BoxFit.cover)),
child: Stack(children: [
Padding(
padding: const EdgeInsets.fromLTRB(20,0,20,0),
child: InkWell(
onTap: () => _launchURL(),
child: Container(
child: Row(
children: [
DefaultText(fontSize: 12.0, color: Colors.white, weight: FontWeight.normal, textData: "By clicking the \"Register\", button confirm that you accept the application"),
DefaultText(fontSize: 12.0, color: Colors.blue, weight: FontWeight.normal, textData: "terms of service and privacy policy."),
],
),
)),
),
]),
),
));
}
}
Use Flexible as below:
Row(
children: [
Flexible(
child:DefaultText(fontSize: 12.0, color: Colors.white, weight: FontWeight.normal, textData: "By clicking the \"Register\", button confirm that you accept the application"),
),
Flexible(
child:
DefaultText(fontSize: 12.0, color: Colors.blue, weight: FontWeight.normal, textData: "terms of service and privacy policy."),
),
],
)
This will warp your text.
But I suggest you should use RichText.
RichText(
text: TextSpan(
text: 'By clicking the \"Register\", button confirm that you accept the application',
style: TextStyle(
color: Colors.black, fontSize: 18),
children: <TextSpan>[
TextSpan(text: 'Terms and policy',
style: TextStyle(
color: Colors.blueAccent, fontSize: 18),
recognizer: TapGestureRecognizer()
..onTap = () {
// navigate to desired screen
}
)
]
),
),
Update:
You can also use library html https://pub.dev/packages/html
try wrapping your children in Flexible() widget
Like this:
Flexible(
Text()
),
A row aligns it's children horizontally, which means your first DefaultText widget is rendered and the second one on the right of it.
What you can do is wrap both children in Expanded and make the text overflow fading and use Text instead of DefaultText :
Stack(children: [
Padding(
padding: const EdgeInsets.fromLTRB(20,0,20,0),
child: InkWell(
onTap: () => _launchURL(),
child: Container(
child: Row(
children: [
Expanded(child:Text(style:TextStyle(fontSize: 12.0, color: Colors.white, fontWeight: FontWeight.normal,overflow: TextOverflow.fade),"By clicking the \"Register\", button confirm that you accept the application")),
Expanded(child:Text(style:TextStyle(fontSize: 12.0, color: Colors.blue, fontWeight: FontWeight.normal,overflow: TextOverflow.fade) ,"terms of service and privacy policy.")),
],
),
)),
),
]),
You should wrap your Container in a Flexible to let your Row know that it's ok for the Container to be narrower than its intrinsic width. Expanded will also work.
Use Flexible in the Row.
Example:Row(
children: [
Flexible(
child: DefaultText(
fontSize: 12.0,
color: Colors.white,
weight: FontWeight.normal,
textData:
"By clicking the \"Register\", button confirm that you accept the application"),
),
Flexible(
child: DefaultText(
fontSize: 12.0,
color: Colors.blue,
weight: FontWeight.normal,
textData: "terms of service and privacy policy."),
)
],
)
I created a custom rounded AppBar using a code found here, but with just a title in the center.
I wanted to add a backbutton in the top left corner inside AppBar and I tried nesting a button and the text in a Row, but the result is that neither the button or the text are shown. Any help?
Here the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class RoundedAppBar extends StatelessWidget implements PreferredSizeWidget {
String title;
RoundedAppBar(this.title);
#override
Widget build(BuildContext context) {
return PreferredSize(
child: LayoutBuilder(builder: (context, constraints) {
final width =
constraints.maxWidth * 16; //per modificare "rotondità" app Bar
return OverflowBox(
maxHeight: double.infinity,
maxWidth: double.infinity,
child: SizedBox(
height: width,
width: width,
child: Padding(
padding: EdgeInsets.only(
bottom: width / 2 - preferredSize.height / 2),
child: Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
color: const Color(0xff000350),
shape: BoxShape.circle,
),
child: Row(
children: [
Align(
alignment: Alignment.centerLeft,
child: IconButton(
color: Colors.black,
icon: Icon(Icons.chevron_left),
onPressed: () => Navigator.pop(context),
),
),
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
],
)),
),
),
);
}),
preferredSize: preferredSize);
}
#override
Size get preferredSize => Size.fromHeight(80);
EDIT:
Tried using ListTile as suggested, something happened but didn't work properly.
Here the result.
child: ListTile(
title: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
leading: IconButton(
color: Colors.white,
icon: Icon(Icons.chevron_left),
onPressed: () => Navigator.pop(context),
),
),
EDIT:
I inserted your code as shown. With trial and error, using 35 as height I was able to see the title, but still no button.
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildBack(true, context),
Container(
height: 35,
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
),
_buildBack(false, context),
],
and
Widget _buildBack(bool isPlaceHolder, BuildContext context) {
return Visibility(
child: InkWell(
child: Icon(
Icons.close,
size: 35,
),
onTap: () => Navigator.of(context, rootNavigator: true).pop('dialog'),
),
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: !isPlaceHolder,
);
}
and here the result
You can use a ListTile and use a IconButton as leading.
ListTile(
leading: IconButton(
icon: Icon(Icons.back),
title: '',
onPressed => Navigator.pop(context),
),
),
Another possibility I see:
As the child from the AppBar
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildBack(true, context),
Container(
height: height,
child: Text(
'$_title',
style: Theme.of(context).textTheme.headline2,
),
),
_buildBack(false, context),
],
),
In another place outside the builder.
Widget _buildBack(bool isPlaceHolder, Buildcontext context) {
return Visibility(
child: InkWell(
child: Icon(
Icons.close,
size: widget.height,
),
onTap: () => Navigator.of(context, rootNavigator: true).pop('dialog'),
),
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: !isPlaceHolder,
);
}}
Here there is again a row as you have tried it yourself, but this one is set up a little differently and an iconButton is built before and after the text, but so that the text remains in the center, the second one is made invisible,