Introduction
The figma_squircle
package allows you to create squircle shapes, which are rounded rectangles with a specific curve. This guide will show you how to integrate and use this package to create squircle shapes in your Flutter app.
Content
1.Add the figma_squircle
dependency:
Open your pubspec.yaml
file and add the figma_squircle
dependency.
dependencies:
figma_squircle: ^latest_version
Run flutter pub get
to install the package.
2.Import the package:
Import the figma_squircle
package in your Dart file.
import 'package:figma_squircle/figma_squircle.dart';
4.Create a squircle shape:
Use the Squircle
widget to create a squircle shape.
Squircle(
size: Size(100, 100),
curve: 50,
child: Container(
color: Colors.blue,
child: Center(
child: Text(
'Squircle',
style: TextStyle(color: Colors.white),
),
),
),
)
Customize the size
and curve
parameters as needed. The curve
parameter determines the curve of the squircle shape, with higher values creating a more rounded shape.
5.Run the app:
Run your Flutter app to see the squircle shape. It should appear as a rounded rectangle with a specific curve.
Sample Code
// ignore_for_file: prefer_const_constructors
import 'package:figma_squircle/figma_squircle.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
const niceGradient = LinearGradient(
colors: [
Color(0xFFFF4286),
Color(0xFFFF6666),
],
);
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Figma Squircles',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({
Key? key,
}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Mode> selected = const <Mode>[];
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: [
CompareExample(),
EditorExample(),
AnimatedExample(),
TilesExample(),
VariationsExample(
key: Key('Mixed'),
selected: selected,
onSelected: (selected) => setState(() => this.selected = selected),
radius: SmoothBorderRadius.only(
topLeft: SmoothRadius(
cornerRadius: 10,
cornerSmoothing: 1,
),
topRight: SmoothRadius(
cornerRadius: 20,
cornerSmoothing: 0.4,
),
bottomLeft: SmoothRadius(
cornerRadius: 5,
cornerSmoothing: 0.8,
),
bottomRight: SmoothRadius(
cornerRadius: 30,
cornerSmoothing: 0.6,
),
),
),
Center(
child: ClipSmoothRect(
radius: SmoothBorderRadius(
cornerRadius: 10,
cornerSmoothing: 1,
),
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
);
}
}
class AnimatedExample extends StatefulWidget {
const AnimatedExample({
Key? key,
}) : super(key: key);
@override
_AnimatedExampleState createState() => _AnimatedExampleState();
}
class _AnimatedExampleState extends State<AnimatedExample> {
int radius = 0;
List<SmoothBorderRadius> animateRadius = [
SmoothBorderRadius(
cornerRadius: 10,
cornerSmoothing: 1,
),
SmoothBorderRadius(
cornerRadius: 50,
cornerSmoothing: 1,
),
SmoothBorderRadius(
cornerRadius: 50,
cornerSmoothing: 0.5,
),
SmoothBorderRadius(
cornerRadius: 25,
cornerSmoothing: 0.5,
),
SmoothBorderRadius(
cornerRadius: 25,
cornerSmoothing: 1,
),
];
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: [
Expanded(
child: Center(
child: AnimatedContainer(
duration: const Duration(seconds: 1),
curve: Curves.elasticOut,
height: 200,
width: 200,
decoration: ShapeDecoration(
gradient: niceGradient,
shape: SmoothRectangleBorder(
borderRadius: animateRadius[radius],
),
),
),
),
),
Text(
"Swipe right for more examples--->",
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold, fontSize: 20),
),
ElevatedButton(
onPressed: () {
setState(() {
radius = (radius + 1) % animateRadius.length;
});
},
child: Text('${animateRadius[radius]}'),
)
],
),
);
}
}
class EditorExample extends StatefulWidget {
const EditorExample({
Key? key,
}) : super(key: key);
@override
_EditorExampleState createState() => _EditorExampleState();
}
class _EditorExampleState extends State<EditorExample> {
double cornerRadius = 0;
double cornerSmoothing = 1.0;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: [
Expanded(
child: Center(
child: AnimatedContainer(
duration: const Duration(seconds: 1),
curve: Curves.elasticOut,
height: 200,
width: 200,
decoration: ShapeDecoration(
gradient: niceGradient,
shape: SmoothRectangleBorder(
borderRadius: SmoothBorderRadius(
cornerRadius: cornerRadius,
cornerSmoothing: cornerSmoothing,
),
),
),
),
),
),
Text(
"Swipe right for more examples--->",
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold, fontSize: 20),
),
Text('radius: ${cornerRadius.toStringAsFixed(1)}, smoothing: ${cornerSmoothing.toStringAsFixed(1)}'),
Slider(
min: 0,
max: 300,
value: cornerRadius,
onChanged: (v) => setState(() => cornerRadius = v),
),
Slider(
min: 0,
max: 1,
value: cornerSmoothing,
onChanged: (v) => setState(() => cornerSmoothing = v),
),
],
),
);
}
}
class TilesExample extends StatelessWidget {
const TilesExample({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
children: [
Container(
margin: EdgeInsets.all(8),
height: 100,
decoration: ShapeDecoration(
gradient: niceGradient,
shape: SmoothRectangleBorder(
borderRadius: SmoothBorderRadius(
cornerRadius: 25,
cornerSmoothing: 1,
),
),
),
),
Text(
"Swipe right for more examples--->",
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold, fontSize: 20),
),
for (var i = 0; i < 100; i++)
Theme(
data: ThemeData.dark(),
child: Card(
child: ListTile(
title: Text('Tile $i'),
subtitle: Text(i % 2 == 1 ? 'Circular' : 'Smooth'),
),
shape: i % 2 == 1
? RoundedRectangleBorder(borderRadius: BorderRadius.circular(25))
: SmoothRectangleBorder(
borderRadius: SmoothBorderRadius(
cornerRadius: 25,
),
),
),
)
],
);
}
}
class CompareExample extends StatelessWidget {
const CompareExample({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Container(
color: Colors.red,
child: Container(
padding: EdgeInsets.all(20),
decoration: ShapeDecoration(
color: Colors.blue.withOpacity(0.5),
shape: SmoothRectangleBorder(
side: BorderSide(
color: Colors.blue,
width: 2,
),
borderRadius: SmoothBorderRadius(
cornerRadius: 16,
cornerSmoothing: 0.0,
),
borderAlign: BorderAlign.outside,
),
),
child: Text('Hello'),
),
),
),
Container(
margin: EdgeInsets.all(8),
width: 200,
height: 200,
decoration: ShapeDecoration(
gradient: niceGradient,
shape: SmoothRectangleBorder(
borderRadius: SmoothBorderRadius(
cornerRadius: 25,
cornerSmoothing: 1,
),
),
),
child: Center(
child: Text(
'Smooth (25,1)',
style: TextStyle(color: Colors.white),
),
),
),
Container(
margin: EdgeInsets.all(8),
width: 200,
height: 200,
decoration: ShapeDecoration(
gradient: niceGradient,
shape: ContinuousRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
child: Center(
child: Text(
'Continuous (50)',
style: TextStyle(color: Colors.white),
),
),
),
Container(
margin: EdgeInsets.all(8),
width: 200,
height: 200,
decoration: BoxDecoration(
gradient: niceGradient,
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: Text(
'Circular (25)',
style: TextStyle(color: Colors.white),
),
),
),
Text(
"Swipe right for more examples--->",
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold, fontSize: 20),
),
],
);
}
}
class VariationsExample extends StatelessWidget {
const VariationsExample({
Key? key,
required this.radius,
required this.selected,
required this.onSelected,
}) : super(key: key);
final List<Mode> selected;
final SmoothBorderRadius radius;
final ValueChanged<List<Mode>> onSelected;
Widget _rectangle() {
return Container(
height: 100,
width: 100,
color: Colors.blue.withOpacity(0.25),
);
}
Widget _circular() {
return Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.75),
borderRadius: radius,
),
);
}
Widget _continuous() {
return Container(
height: 100,
width: 100,
decoration: ShapeDecoration(
color: Colors.red.withOpacity(0.75),
shape: ContinuousRectangleBorder(
borderRadius: radius,
),
),
);
}
Widget _smooth() {
return Container(
height: 100,
width: 100,
decoration: ShapeDecoration(
color: Colors.red.withOpacity(0.75),
shape: SmoothRectangleBorder(
borderRadius: radius,
),
),
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: Stack(
alignment: Alignment.center,
children: [
if (selected.contains(Mode.rectangle)) _rectangle(),
if (selected.contains(Mode.circular)) _circular(),
if (selected.contains(Mode.continuous)) _continuous(),
if (selected.contains(Mode.smooth)) _smooth(),
],
),
),
Wrap(
children: [
ModeChip(
mode: Mode.rectangle,
selected: selected,
onSelected: onSelected,
),
ModeChip(
mode: Mode.circular,
selected: selected,
onSelected: onSelected,
),
ModeChip(
mode: Mode.smooth,
selected: selected,
onSelected: onSelected,
),
ModeChip(
mode: Mode.continuous,
selected: selected,
onSelected: onSelected,
),
],
)
],
);
}
}
enum Mode {
rectangle,
smooth,
circular,
continuous,
}
class ModeChip extends StatelessWidget {
ModeChip({
required this.mode,
required this.selected,
required this.onSelected,
}) : super(key: ValueKey(mode));
final Mode mode;
final List<Mode> selected;
final ValueChanged<List<Mode>> onSelected;
@override
Widget build(BuildContext context) {
return FilterChip(
label: Text(mode.toString()),
selected: selected.contains(mode),
onSelected: (bool value) {
onSelected([
...selected.where((x) => x != mode),
if (value) mode,
]);
},
);
}
}
Output
Conclusion
By following these steps, you can easily integrate the figma_squircle
package into your Flutter app and create squircle shapes. This can be useful for creating unique and visually appealing UI elements in your app.