How to define Custom BorderRadius class in flutter? - 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),
),
);
}
}

Related

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),
],
),
);
}
}

Flutter Floating action button error! Trying to create a row of button with a responsive touch effect

My Code:
bool _isClicked = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0),
child: Container(
decoration: BoxDecoration(
color: _isClicked ? Colors.orange[300] : Colors.white,
borderRadius: BorderRadius.circular(30.0),
),
child: FlatButton(
splashColor: Colors.orange[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
onPressed: () {
setState(() {
_isClicked = !_isClicked;
});
},
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
),
child: Text(
foodItem,
style: TextStyle(
fontSize: 20.0,
color: _isClicked ? Colors.white : Colors.grey[700],
),
),
),
),
),
),
);
Reality:
Expectation:
When I click one button, only that turns orange the rest stay white.
When I click it back again, it turns grey again just like the rest.
I believe you want to achieve some kind toggle behavior for the buttons. Though ToggleBar widget is good for this it is not flexible with it expectations about child widgets. So a ButtonBar widget would be helpful with some kind internal state about the buttons which are clicked. Here is a working solution which might help you. The same code is available as a codepen here.
Approach
Extracted your code for the button into a widget called TButton with parameters as follows
isClicked - a boolean flag to denote if the button is clicked.
foodItem - the text to be displayed on the button.
onPressed - a callback function to be called when the button is pressed.
In the parent widget MyButtons hold a list of bool indicating the status of click for each button.
MyButtons accepts a list of foodItems. Iterate this list and generate a list of TButton widget and pass it to the ButtonBar as children.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue, scaffoldBackgroundColor: darkBlue),
home: Scaffold(
body: MyButtons(foodItems: ['Pizza', 'Burger', 'Kebab']),
),
);
}
}
class MyButtons extends StatefulWidget {
MyButtons({Key key, this.foodItems}) : super(key: key);
final List<String> foodItems;
#override
_MyButtonsState createState() => _MyButtonsState();
}
class _MyButtonsState extends State<MyButtons> {
List<bool> isSelected;
#override
initState() {
super.initState();
// initialize the selected buttons
isSelected = List<bool>.generate(widget.foodItems.length, (index) => false);
}
#override
Widget build(BuildContext context) {
return Padding(
// just for aesthetics
padding: const EdgeInsets.only(top: 80.0),
child: ButtonBar(
// use the alignment to positon the buttons in the screen horizontally
alignment: MainAxisAlignment.center,
// iterate over the foodItems and generate the buttons.
children: widget.foodItems.asMap().entries.map((entry) {
return TButton(
isClicked: isSelected[entry.key],
foodItem: entry.value,
onPressed: () {
setState(() {
isSelected[entry.key] = !isSelected[entry.key];
});
});
}).toList(),
),
);
}
}
class TButton extends StatelessWidget {
final bool isClicked;
final String foodItem;
/// OnPressed is passed from the parent. This can be changed to handle it using any state management.
final Function onPressed;
TButton(
{#required this.isClicked,
#required this.foodItem,
#required this.onPressed});
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: isClicked ? Colors.orange[300] : Colors.white,
borderRadius: BorderRadius.circular(30.0),
),
child: FlatButton(
splashColor: Colors.orange[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
onPressed: onPressed,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
),
child: Text(
foodItem,
style: TextStyle(
fontSize: 20.0,
color: isClicked ? Colors.white : Colors.grey[700],
),
),
),
),
);
}
}

Create a progress bar indicator shapes in flutter

We have a problem about our delivery system with progress indicator. Does anyone can suggest a library of progress indicator for flutter. The progress has a shape design. The sample image below.
Progress indicator image sample
You can achieve this using a Row, Containers and CustomClipper class. I've created a library for this purpose. You can use the library from here: progress_stepper.
The following code creates a stepper:
ProgressStepper(
width: 300,
height: 15,
stepCount: 5,
builder: (index) {
double widthOfStep = 300 / 5;
if (index == 1) {
return ProgressStepWithArrow(
width: widthOfStep,
defaultColor: Color(0xFFCECECF),
progressColor: Color(0xFFFBB040),
wasCompleted: true,
);
}
return ProgressStepWithChevron(
width: widthOfStep,
defaultColor: Color(0xFFCECECF),
progressColor: Color(0xFFFBB040),
wasCompleted: false,
);
},
)
It will create a Stepper like the following image:
You can copy paste run full code below
You can use package https://pub.dev/packages/clippy_flutter and https://pub.dev/packages/step_progress_indicator
When step index == 0 return Point else return Chevron
code snippet
StepProgressIndicator(
totalSteps: 3,
currentStep: 2,
size: 20,
selectedColor: Colors.orangeAccent,
unselectedColor: Colors.grey,
customStep: (index, color, _) => index == 0
? Point(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
))
: Chevron(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
)),
),
working demo
full code
import 'package:flutter/material.dart';
import 'package:clippy_flutter/clippy_flutter.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
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>[
StepProgressIndicator(
totalSteps: 3,
currentStep: 2,
size: 20,
selectedColor: Colors.orangeAccent,
unselectedColor: Colors.grey,
customStep: (index, color, _) => index == 0
? Point(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
))
: Chevron(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
)),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Flutter - AnimatedBuilder , animation/widget bugs out when loading in for first time

when I load the builder for the first time , all of my cards are the same size for a second before jumping to the correct sizes and proportions ,does anyone know how I can adjust this so that they are in the right sizes from the get go?
Strangely enough when I replace my Padding & Card widget with just a container full of the images, it seems to spawn in the correct sizes , however I need them to be cards for my later layout.
(I also plan on throwing it all into a widget class instead of putting all this code in my main and rather just returning a CustomScroller.)
Please check the following Gifs:
Gif Of Animation Glitch
Gif of Animation working fine when just container is used
Any help fixing the initial loading would be wildly appreciated! :)
import 'package:flutter/material.dart';
import 'package:blink/widget/customScroller.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
List<String> images = [
"https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
"https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
"https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
];
#override
void initState() {
// TODO: implement initState
pageController = PageController(initialPage: 1, viewportFraction: 0.77);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: images.length,
itemBuilder: (context,position){
return customScroller(position);
}),);
}
customScroller(int index) {
return AnimatedBuilder(
animation: pageController,
builder: (context, widget) {
double val = 1;
if(pageController.position.haveDimensions){
val = pageController.page - index;
val = 1 - (val.abs()*0.3).clamp(0.0,1.0);}
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(val) *300,
width: Curves.easeInOut.transform(val) *400,
child: widget,
),
);
},
// child: Container(
// margin: EdgeInsets.all(10),
// child: Image.network(images[index],fit:BoxFit.cover),
// ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
child: Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
child: Container(
child: Card(
color: Colors.white70,
elevation: 9,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
clipBehavior: Clip.antiAlias,
child: Container(
color: Colors.white,
padding: EdgeInsets.all(5),
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
height: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(0.0),
bottomRight: Radius.circular(0.0),
bottomLeft: Radius.circular(20.0)),
child: new Image.network(
images[index],
fit: BoxFit.cover,
),
),
),
),
],
),
),
),
),
)
);
}
}
What you are missing is that the AnimatedBuilder build method runs only if there is some animation. Not at the very beginning. So this is why the size changes if you are scrolling and not before.
Your child widget is not wrapped with a transformer widget (or sized box) so it stays the same for all indexes (at the beginnen - the builder has not run yet). In my example I wrapped the child also with a SizedBox and i gave val some initial value.
Working example:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
List<String> images = [
"https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
"https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
"https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
];
#override
void initState() {
// TODO: implement initState
pageController = PageController(initialPage: 1, viewportFraction: 0.77);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: images.length,
itemBuilder: (context, position) {
return customScroller(position);
}),
);
}
customScroller(int index) {
Widget child = Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
child: Container(
child: Card(
color: Colors.white70,
elevation: 9,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
clipBehavior: Clip.antiAlias,
child: Container(
color: Colors.white,
padding: EdgeInsets.all(5),
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
height: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(0.0),
bottomRight: Radius.circular(0.0),
bottomLeft: Radius.circular(20.0)),
child: new Image.network(
images[index],
fit: BoxFit.cover,
),
),
),
),
],
),
),
),
),
);
double val = (index == 1)?1:0.7;
return AnimatedBuilder(
animation: pageController,
builder: (context, widget) {
if (pageController.position.haveDimensions) {
val = pageController.page - index;
val = 1 - (val.abs() * 0.3).clamp(0.0, 1.0);
}
print("val: $val; index: $index");
return _getTransformedSizedBox(val, widget);
},
// child: Container(
// margin: EdgeInsets.all(10),
// child: Image.network(images[index],fit:BoxFit.cover),
// ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
child: _getTransformedSizedBox(val, child));
}
_getTransformedSizedBox(double val, Widget widget) {
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(val) * 300,
width: Curves.easeInOut.transform(val) * 400,
child: widget,
),
);
}
}

Is there a way to change the shape of a Dialog?

I was looking at the properties for the different dialog classes and didn't see anything that would change it's shape. Is there a way to change a dialogs shape?
You can create a variety of shaped dialogs using Container in combination with existing clipping widgets (Painting and Effect Widgets) or by extending CustomClipper. The below will give you a diamond-shaped dialog. There are existing widgets like ClipOval that work out of the box without any customization (see screenshot below). If you want to try out ClipOval, simply replace ClipPath with ClipOval and comment out clipper:. Check out the painting.dart class to learn about creating custom paths.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Shaped Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
dialogBackgroundColor: Colors.transparent,
),
home: MyHomePage(title: 'Flutter Shaped Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_showShapedDialog();
}),
);
}
_showShapedDialog() {
showDialog(
context: context,
builder: (context) {
return Padding(
padding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
child: ClipPath(
child: Material(
color: Colors.white,
child: Center(
child: Container(
alignment: FractionalOffset.center,
height: MediaQuery.of(context).size.width / 2.0,
width: MediaQuery.of(context).size.width / 2.0,
decoration: BoxDecoration(
border: Border.all(),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Text(
'Clipping to a path is expensive. Certain shapes have more optimized widgets.',
textAlign: TextAlign.center,
),
),
FlatButton(
child: Text(
'OK',
style: TextStyle(color: Colors.blue),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
),
clipper: _MyClipper(), // Comment this out if you want to replace ClipPath with ClipOval
),
);
},
);
}
}
class _MyClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
path.lineTo(size.width / 2.0, 0.0);
path.lineTo(0.0, size.height / 2.0);
path.lineTo(size.width / 2.0, size.height);
path.lineTo(size.width, size.height / 2.0);
path.lineTo(size.width / 2.0, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Like that
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Text('Dialog'),
);
AlertDialog(
shape: RoundedRectangleBorder(borderRadius:
BorderRadius.all(Radius.circular(15))),
title: Text('Your title!'),
content: Container(),
);