How can I center a flutter_markdown Widget vertically? - flutter

As you can see in the Image there is a Container-widget (grey Box) and in it there's a Markdown-widget from the flutter_markdown Package.
I want that the Markdown-element is centered vertially in the Container ( where the yellow marker is) instead of where the Markdown is now ("Internet").
EDIT:
If the only possible solution is to add a fixed width I need to calculate it somehow, because it can be only one or many lines or a long text without line breaks. If there aren't any line breaks the flutter_markdown widget automatically wraps the text into the widget.
How should it look like
child: Container(
constraints: BoxConstraints.expand(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.width * 0.7,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
color: _color
),
padding: EdgeInsets.all(8.0),
alignment: Alignment.center,
child: Container(
decoration: BoxDecoration(
borderRadius: new BorderRadius.only(
topLeft: new Radius.circular(20.0),
bottomLeft: new Radius.circular(20.0),
),
boxShadow: [
new BoxShadow(
color: _color,
offset: new Offset(5.0, 5.0),
blurRadius: 20.0,
)
],
),
child: Scrollbar(
child: Markdown(
imageDirectory: Store.storageDirectory,
data: _markdownText)),
),
),
Thanks in advance.

Markdown based on ListView and provide the same properties. Works for me:
Center(child: Markdown(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
data: store.subtitle))

Related

Flutter: How to make height (or width) change dynamically depending on the parent | Card with colored border

I have created a Card whose height depends on its content, so it's height is not defined anywhere. Now I want to add a left blue border to the Card, whose height adjusts to the current height of the Card (his parent).
So when I type in any fixed height (e.g. 50), the blue border looks like this:
height: 50
This is my Code:
Card(
margin: EdgeInsets.zero,
elevation: 0,
color: Colors.black12,
shape: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderSide: BorderSide.none,
),
child: Container(
width: double.infinity,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("This is random text."),
Text("There can be more."),
Text("So the height of this Card is never fix."),
],
),
),
Container(
height: 50, // This height must match the current height of the Card
width: 8,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(topLeft: Radius.circular(6), bottomLeft: Radius.circular(6))
),
)
],
),
),
)
But I want a dynamic height, with which it should look always like this, whether the content changes or not:
height: matches current height of Card
Neither double.infinity helped me nor an Expanded Widget.
You can use Container's decoration as parent and ClipRRect to round the corners. You can also wrap with Card if you feel needed.
Padding(
padding: const EdgeInsets.all(24.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.grey,
border: Border(
left: BorderSide(
color: Colors.blue,
width: 12,
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: const [
Text("This is random text."),
Text("There can be more."),
Text("So the height of this Card is never fix."),
],
),
),
)),
A way to do this with much less code:
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
// add Card-like elevation
boxShadow: kElevationToShadow[4],
gradient: LinearGradient(
stops: const [0.03, 0.03],
colors: [
Colors.blue,
Colors.grey[900]!,
],
),
borderRadius: BorderRadius.circular(3),
),
child: const Text(' Sunt magna irure ut reprehenderit.'),
),
If you use a gradient you might want to add some padding on the left of the text though since it might go into that "Color Marker" in the next line depending on how big the width is.
Result

Give a borderRadius for non-uniform borders

I need a container which has borders only on top, bottom and right side. In addition the bottomRight and topRight corners should be rounded.
Here is my code for some context:
Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.45),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
topRight: Radius.circular(20)),
border: Border(
top: BorderSide(
color: Colors.white.withOpacity(0.45),
width: 4.0),
bottom: BorderSide(
color: Colors.white.withOpacity(0.45),
width: 4.0),
right: BorderSide(
color: Colors.white.withOpacity(0.45),
width: 4.0),
),
...
With this code I produce the following error, which requires borderRadius to have uniform borders (which I do not want in this case).
Error to circumvent:
════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during paint():
A borderRadius can only be given for a uniform Border.
I have 2 options:
1, You will need learn about create CustomPainter. You can customize your border by create a Paint and path.
2, Use two Container.
Container(
height: 48,
width: 200,
padding: EdgeInsets.all(4).copyWith(left: 0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.45),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
topRight: Radius.circular(20)),
),
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.45),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
topRight: Radius.circular(20)),
),
),
),
I found a solution, which also works for transparent colors:
Wrap the container with a Stack() and use another Container() to
hide the left border. For the desired effect give both
containers the same color and adjust the height (deduct 2x border width from the 1st Container to get the height of the 2nd Container).
To position the "Border"-Container to the left add alignment: Alignment.centerLeft, to the stack.
In order to show a text within this custom container, you need to position the Child-Widget (which you would directly add to the child parameter of the first container) as a separate widget to a Row() with your Child-Widget and the "Border"-Container as its children.
To align the Child-Widget correctly, use the row´s mainAxisAlignment: MainAxisAlignment.spaceBetween, and wrap the Child-Widget with Padding() to ensure the "Border"-Container will stick to the left border.
Here is the code for the desired widget:
Stack(
alignment: Alignment.centerLeft,
children: [
Container(
height: 493.0,
width: 1353.0,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 4.0),
color: Colors.black.withOpacity(0.45),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
topRight: Radius.circular(20),
),
boxShadow: [
CustomBoxShadow(
color: Colors.white,
blurRadius: 15.0,
blurStyle: BlurStyle.outer,
)
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Acts as the left border
Container(
width: 4.0,
height: 485.0,
color: Colors.black,
),
SizedBox(width: 115.0),
Padding(
padding: const EdgeInsets.only(
right: 75.0,
),
child: Text(
"Add the child widget here",
style: TextStyle(color: Colors.white),
), // Add text here
)
],
)
],
),
For your information: If you want a BoxShadow, you run into the problem that it will change your transparent container color, as Flutter draws the shadow behind the widget. I added a CustomBoxShadow below, which allows to change the default blurStyle. Use blurStyle: BlurStyle.outer, to keep your desired transparent background color of the container. The code is from here: SO-Link.
class CustomBoxShadow extends BoxShadow {
final BlurStyle blurStyle;
const CustomBoxShadow({
Color color = const Color(0xFF000000),
Offset offset = Offset.zero,
double blurRadius = 0.0,
this.blurStyle = BlurStyle.normal,
}) : super(color: color, offset: offset, blurRadius: blurRadius);
#override
Paint toPaint() {
final Paint result = Paint()
..color = color
..maskFilter = MaskFilter.blur(this.blurStyle, blurSigma);
assert(() {
if (debugDisableShadows) result.maskFilter = null;
return true;
}());
return result;
}
}

RectangleBox In Flutter

In my code, there is this CircleAvtar which I want to replace it with a big rectangular box. I am new to flutter I am finding it difficult to achieve this.
child: Card(
elevation: 3,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
child: Container(
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
10,
),
// border: Border.all(width: 0.5),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
color: whiteColor,
),
child: expertiseSearchModel.userImageURL.isEmpty
? CircleAvatar(
radius: 35,
child: SvgPicture.asset(
'assets/images/default_user_image.svg',
// height: screenUtil.setSp(80),
// width: screenUtil.setSp(80),
fit: BoxFit.contain,
),
)
: CircleAvatar(
radius: 35,
backgroundImage:
NetworkImage(expertiseSearchModel.userImageURL),
),
),
I want it to look like this :
If you can show us what your current code is giving the output maybe I can help you more. But As far as i understood this, you can simple use Image.Network() to show the image and remove the circular avatar
Try this, if it works if not lemme know I will edit it accordingly
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
color: whiteColor,
),
child: expertiseSearchModel.userImageURL.isEmpty
? CircleAvatar(
radius: 35,
child: SvgPicture.asset(
'assets/images/default_user_image.svg',
// height: screenUtil.setSp(80),
// width: screenUtil.setSp(80),
fit: BoxFit.contain,
),
)
: Image.network(expertiseSearchModel.userImageURL)
),
Inside your main container use the column as a child and put another container as a child and use the Image decoration property of the container to display pictures. You can change the border-radius of the child container to have those circular edges.

How to add a border/corner radius to a LinearProgressIndicator in Flutter?

I am trying to add a border radius to a LinearProgressIndicator in Flutter.
When I replace the LinearProgressIndicator with another widget (e.g. Text) in the code below, it works, as expected.
Container(
decoration: new BoxDecoration(
borderRadius:
new BorderRadius.all(const Radius.circular(20.0))),
child: LinearProgressIndicator(
value: _time,
),
)
1) Using Widget
Container(
margin: EdgeInsets.symmetric(vertical: 20),
width: 300,
height: 20,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: LinearProgressIndicator(
value: 0.7,
valueColor: AlwaysStoppedAnimation<Color>(Color(0xff00ff00)),
backgroundColor: Color(0xffD6D6D6),
),
),
)
2) Using dependency
List of different types indicator https://pub.dev/packages/percent_indicator
Try this template code
child: Padding(
padding: EdgeInsets.all(15.0),
child: LinearPercentIndicator(
width: MediaQuery.of(context).size.width - 50,
animation: true,
lineHeight: 20.0,
animationDuration: 2000,
percent: 0.9,
linearStrokeCap: LinearStrokeCap.roundAll,
progressColor: Colors.greenAccent,
),
)
Edit: I just wanted to point out my answer doesn't account for rounding the end of the 'value' fill inside the bar, which the OP wanted. However it seems many people came to this question looking for the answer I provided, (as did I before I found the answer and came back to respond).
So if you need the inside of this indicator also to have a rounded edge, as of now I think the accepted answer from Amit is the best route. If the inside of the indicator can have a flat edge and you don't want to use a third party package, I think my answer below is still the best option.
Original:
You actually don't need to use a third party package, and can wrap your LinearProgressIndicator with the ClipRRect widget and give it a circular border radius. If you want to give it a specific thickness/height then you could use a container as an intermediary:
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Container(
height: 10,
child: LinearProgressIndicator(
value: 0.35, // percent filled
valueColor: AlwaysStoppedAnimation<Color>(Colors.orange),
backgroundColor: Color(0xFFFFDAB8),
),
),
)
would produce this, if placed in another widget with a defined width:
Let's try my custom progress bar, simple and don't use any library :)
class ProgressBar extends StatelessWidget {
final double max;
final double current;
final Color color;
const ProgressBar(
{Key? key,
required this.max,
required this.current,
this.color = AppColors.secondaryColor})
: super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (_, boxConstraints) {
var x = boxConstraints.maxWidth;
var percent = (current / max) * x;
return Stack(
children: [
Container(
width: x,
height: 7,
decoration: BoxDecoration(
color: Color(0xffd3d3d3),
borderRadius: BorderRadius.circular(35),
),
),
AnimatedContainer(
duration: Duration(milliseconds: 500),
width: percent,
height: 7,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(35),
),
),
],
);
},
);
}
}
You can try this code:
Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(40.0))),
child: const ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(20)),
child: LinearProgressIndicator(
minHeight: 5.0,
value: 0.2,
color: Colors.white,
backgroundColor: Color(0xFF3B2D73),
),
),
I am going to leave my answer in case someone is looking for something custom, basic with custom BorderRadius
Container(
height: 24.0,
margin: EdgeInsets.only(top: 12.0, bottom: 2.0),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
clipBehavior: Clip.antiAlias,
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: 0.57,
heightFactor: 1.0,
child: Container(
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
clipBehavior: Clip.antiAlias,
),
),
),
Feel free to try it out :)
Do not need to wrap LinearPercentIndicator inside a Container widget. You could get the desired output only using LinearPercentIndicator.
See the template code
LinearPercentIndicator(
lineHeight: 40.0,
barRadius: const Radius.circular(20.0),
percent: 0.7,
animation: true,
animationDuration: 1000,
backgroundColor: Color(0xFFD6D6D6),
progressColor: Color(0xFF5BFB82),
),
To make the inner bar rounded, we need to use the following logic :
Make the Outer progress bar rounded, use ClipRRect and set borderRadius
To make the inner bar rounded, we can use Container, where we will make one side (right side) rounded using borderRadius. Then, we will place it on top of our progress bar, using Stack.
The width of the container will be actually the progress shown in the progress bar.
Container(
width: (MediaQuery.of(context).size.width - 30) *
calculateProgressBarValue(Data1, Data2),
height: 6,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(CommonDimens.MARGIN_10),
bottomLeft: Radius.circular(CommonDimens.MARGIN_10),
),
color: progressBarColor,
),
Full code :
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(10)),
child: Stack(
children: [
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(10)),
child: LinearProgressIndicator(
minHeight: 6.0,
valueColor:
AlwaysStoppedAnimation<Color>(Colors.grey),
value: 1,
),
),
Positioned(
right: 0,
child: Container(
width: ((MediaQuery.of(context).size.width) - 30) *
calculateProgressBarValue(Data1,Data2),
height: 6,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(CommonDimens.MARGIN_10),
bottomLeft: Radius.circular(CommonDimens.MARGIN_10),
),
color: progressBarColor,
),
),
],
),
);
You can make use of
curved_progress_bar , It has both CurvedCircularProgressIndicator as well as CurvedLinearProgressIndicator, and it works just like normal CircularProgressIndicator and LinearProgressIndicator.
You could try my library (capped_progress_indicator) that does what you want and works exactly like Flutter's original LinearProgressIndicator and CircularProgressIndicator. It not only rounds the ends of the track/background but also the ends of the progress/indicator.
So its just a matter of installing the package and changing your code from
LinearProgressIndicator(
// ...
)
to
import 'package:capped_progress_indicator/capped_progress_indicator.dart';
LinearCappedProgressIndicator(
// ...
)
You can also change the corner radius to your liking
LinearCappedProgressIndicator(), // Circle end (default).
LinearCappedProgressIndicator(cornerRadius: 5), // Rounded end.
LinearCappedProgressIndicator(cornerRadius: 0), // Square end.

SingleChildScroll view not scrolling

I probably misuse the widget. I want to make a card scrollable because it overflows on smaller devices :
My code is :
LayoutBuilder(
builder:(BuildContext context,BoxConstraints viewportConstraints){
return _currentItem == 1 ? FadeTransition(
opacity: fadeAnimation,
child: SingleChildScrollView(
child: new HotelAdditionnalInfo(),
),
HotelAdditionnalInfo() is a widget with a fixed height (that's why I want to make it scrollable) being :
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, 5.0),
blurRadius: 15.0
),
]
),
width: MediaQuery.of(context).size.width * 0.9,
height: 300.0,
child: Stack( ...
Adding SingleChildScrollView doesn't seem to change anything, there is still this yellow overflow :/
Try wraping your SingleChildScrollView into a Container and then give that Container a height say 300 for example.
Container(
height:300,
child: SingleChildScrollView(
child: new HotelAdditionnalInfo(),
),
),