drawing partial round-rect borders - flutter

i want to be able to draw partial round-rect borders around a child widget: only the left, top, and right sides; only the left, bottom and right sides; and so on. this function comes tantalizingly close to doing what i want:
Widget roundRectBorderTop(Widget child, Color color, double cornerRadius,
[double borderWidth = 1.0])
{
final side = BorderSide(color:color, width:borderWidth);
final bord = Border(left:side, top:side, right:side);
final radi = BorderRadius.circular(cornerRadius);
final data = BoxDecoration(border:bord, borderRadius:radi);
return DecoratedBox(child:child, decoration:data);
}
alas, when i run this, it dies with the following assertion:
flutter: The following assertion was thrown during paint():
flutter: A borderRadius can only be given for uniform borders.
flutter: 'package:flutter/src/painting/box_border.dart':
flutter: Failed assertion: line 510 pos 12: 'borderRadius == null'
if i remove the borderRadius: parameter from the BoxDecoration object, then the code "works," but it draws right-angle corners, rather than round-rect corners, which is what i want.
does anybody know how to fix this?

You could simplify by having BorderRadius.only for decoration of a Container;
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
)
),
child: ...
)
Full working code for the screenshot below;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Rounded Corners Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
padding: EdgeInsets.all(20.0),
child: Text('Rounded Corners'),
),
],
),
),
),
);
}
}

Related

Adjust Width from the Left Side of Container

Changing the width of a container defaults to resizing from the right side.
The pseudocode below has an example where dx is a variable that can change. When it increases or decreases, the container will always grow or shrink from the right side.
Is there a simple way to switch the direction so that the width will increase or decrease from the left side instead of the right side?
Container(
width: dx,
height:200
)
Here is a dartpad gist that shows how the right side of the container's width changes when dragged. What I'm asking is if there is a quick and simple way to make the left side expand/contract without having to animate the position of the container: https://dartpad.dev/?id=ebbe57041bf950018fe5733674c68b20
I checked out your dartpad code. To achieve what you want, I suggest you put two empty Containers on either side of your handles and decrease their size when the handles are dragged (your center Container should also be inside an Expanded widget to take up all the allowed space). here is the example code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
// Application name
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
// Application theme data, you can set the colors for the application as
// you want
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double? rightContainerWidth, leftContainerWidth;
#override
Widget build(BuildContext context) {
rightContainerWidth ??= MediaQuery.of(context).size.width / 2 - 20;
leftContainerWidth ??= MediaQuery.of(context).size.width / 2 - 20;
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Wrap(
children: <Widget>[
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
// left handle
Container(
width: leftContainerWidth,
),
GestureDetector(
onHorizontalDragUpdate: (DragUpdateDetails details) {
setState(() {
leftContainerWidth = details.globalPosition.dx;
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
bottomLeft: Radius.circular(20),
)),
width: 10,
height: 200)),
Expanded(
child: Container(
// padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: ClipRect(
child: Container(
// width: _counter+0.2,
height: 200,
color: Colors.green,
))),
),
GestureDetector(
onHorizontalDragStart: (DragStartDetails details) {
print("st: ${details.localPosition.dx}");
// dx for start is the x offset of the mouse relative to the container
// changeX = (_counter as double) - details.localPosition.dx.floor();
},
onHorizontalDragUpdate: (DragUpdateDetails details) {
setState(() {
// print(details.localPosition.dx);
rightContainerWidth = MediaQuery.of(context).size.width -
details.globalPosition.dx;
});
},
child: Container(
width: 10,
height: 200,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
bottomRight: Radius.circular(20),
)))),
Container(
width: rightContainerWidth,
),
])
],
),
),
);
}
}
Caution: I did not add conditional statements to prevent overflows, make sure you also add them!
Use Wrap Widget
A widget that displays its children in multiple horizontal or vertical runs.
A Wrap lays out each child and attempts to place the child adjacent to the previous child in the main axis, given by direction, leaving spacing space in between. If there is not enough space to fit the child, Wrap creates a new run adjacent to the existing children in the cross axis.
After all the children have been allocated to runs, the children within the runs are positioned according to the alignment in the main axis and according to the crossAxisAlignment in the cross axis.
The runs themselves are then positioned in the cross axis according to the runSpacing and runAlignment.
Example:
Wrap(
spacing: 8.0, // gap between adjacent chips
runSpacing: 4.0, // gap between lines
children: <Widget>[
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: const Text('AH')),
label: const Text('Hamilton'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: const Text('ML')),
label: const Text('Lafayette'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: const Text('HM')),
label: const Text('Mulligan'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: const Text('JL')),
label: const Text('Laurens'),
),
],
)

how to make border of container like this in flutter?

I want to make a container border like this but don't know what should I use?
TRy following this code . You have to customize it more to suit your exact needs. Here we are using BoxDecoration properties to set every corner radius. Check at https://dartpad.dev/?id=61468d155191404e24d99404ebb297ea. This one matches the desgn consideration to a certain level but not exact. This one is simple , other wise to make exact the same as you shown you can use ClipPath.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(right: 16,left: 16,top: 16,bottom: 64),
height: MediaQuery.of(context).size.height*0.80,
width: MediaQuery.of(context).size.width-32,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(MediaQuery.of(context).size.width*.4),
bottomRight: Radius.circular(32.0),
topRight: Radius.circular(0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(1),
offset: Offset(2, 2),
blurRadius: 10.0),
],
),
);
}
}

showModalBottomSheet and Border Radius

I want to make a showModalBottomSheet with a container in Flutter. I want this container to have rounded the top borders but, when I tried this, there are a few small uncolored spaces in the corners. How can I delete them?
This is the code I used:
class OverlayWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ElevatedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.80,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Center(...),
);
},
);
},
);
}
}
The resultant widget is the following:
I want to delete the white spaces in the top border.
Thank you in advance
Reviewing the documentation I realize that the showModalBottomSheet function has a property called 'backgroundColor' 🤦‍♀️
Just adding:
backgroundColor: Colors.transparent,
to the showModalBottomSheet it works.
Thanks for the help anyway!
ThemeData has bottomSheetTheme parameter, you can override this as following :
MaterialApp(
...
theme: ThemeData(
...
bottomSheetTheme:
BottomSheetThemeData(backgroundColor: Colors.transparent),
),
...
),
This will give transparent color for the bottomSheet

Flutter container gets disappear

Don't know what I am missing here. Want to make the Container UI like the Material Filled Text Field. Just want to know whether we can use BorderSide and borderRadius together or they work separately. And using Container only How can I achieve this?
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Container(
height: 50.0,
width: 500.0,
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 2.0, color: Color(0xFFFF7F7F7F)),
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(2),
topRight: Radius.circular(2),
),
color: Color(0xFFBFBFBF),
),
child: const Text('OK',
textAlign: TextAlign.center,
style: TextStyle(color: Color(0xFF000000))),
),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4);
}
}
I think that flutter can't handle this configuration.
You are appling bottom border in the container, and also a border radius.
Read this post: A borderRadius can only be given for uniform borders
Also read this: Add border to a Container with borderRadius in Flutter
In the second post, you may find a way to achieve what you are looking for.

How to define Custom BorderRadius class in flutter?

to standardize the design and avoid mistakes and reduce build time,
I'm trying to define a BorderRadius class that takes a double corner value as an argument so It can be used in many places throughout the app
i'm getting lots of errors with defining the class constructors and can't really get the solution here
import 'package:flutter/material.dart';
class Borderz extends BorderRadius{
final BorderRadius enBorderz;
final double corner;
static const double zeroCorner = 0.0,
const Borderz({
#required this.corner,
this.enBorderz = BorderRadius.only(
topLeft: Radius.circular(corner),
topRight: Radius.circular(corner),
bottomLeft: Radius.circular(corner),
bottomRight: Radius.circular(zeroCorner),
)
}) : super(zeroCorner : zeroCorner)
}
some serious fundamental mistake here in this code that makes me feel embarrassed, appreciate your help
You can copy paste run full code below
You can directly call super.only and no need to use enBorderz
class Borderz extends BorderRadius {
final double corner;
static const double zeroCorner = 0.0;
Borderz({
#required this.corner,
}) : super.only(
topLeft: Radius.circular(corner),
topRight: Radius.circular(corner),
bottomLeft: Radius.circular(corner),
bottomRight: Radius.circular(zeroCorner),
);
}
...
Container(
width: 100,
height: 100,
child: Center(
child: Text(
'test',
),
),
decoration: BoxDecoration(
borderRadius: Borderz(corner: 10.0),
color: Colors.blue,
),
),
working demo
full code
import 'package:flutter/material.dart';
class Borderz extends BorderRadius {
final double corner;
static const double zeroCorner = 0.0;
Borderz({
#required this.corner,
}) : super.only(
topLeft: Radius.circular(corner),
topRight: Radius.circular(corner),
bottomLeft: Radius.circular(corner),
bottomRight: Radius.circular(zeroCorner),
);
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 100,
height: 100,
child: Center(
child: Text(
'test',
),
),
decoration: BoxDecoration(
borderRadius: Borderz(corner: 10.0),
color: Colors.blue,
),
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}