I was wondering how can I achieve something like this, this kind of shape?
Here:
class Draw extends StatelessWidget {
const Draw({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: 300,
height: 170,
child: Stack(
clipBehavior: Clip.none,
children: [
Center(
child: ClipPath(
clipper: MyClipper(),
child: Container(
width: 300,
height: 170,
color: Colors.black,
),
),
),
Positioned(
left: -20,
child: SizedBox(
height: 170,
child: Center(
child: Material(
elevation: 3,
color: Colors.black,
shadowColor: Colors.white,
borderRadius: BorderRadius.circular(10),
child: const SizedBox(width: 80, height: 80),
),
),
),
)
],
),
),
),
);
}
}
class MyClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final p = Path();
double facotr = 30;
p.moveTo(10, 0);
p.lineTo(10, size.height - 20);
p.quadraticBezierTo(10, size.height, 20, size.height);
p.lineTo(size.width - facotr, size.height - facotr);
p.lineTo(size.width, size.height / 2);
p.lineTo(size.width - facotr, facotr);
p.lineTo(20, 0);
p.quadraticBezierTo(10, 0, 10, 10);
return p;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
There is the Paint widget, but also someone made a tool for that wich makes it convienent.
Shape Maker
Related
I'm following this speed code tutorial(https://www.youtube.com/watch?v=KO_PYJKHglo) and I'm facing some problems during somewhere on 6:04.
I did some typing ! and ? for any null safety related problems but nothing had changed.
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/clipper.dart';
import 'package:secondlife_mobile/wave_base_painter.dart';
import 'package:secondlife_mobile/wave_color_painter.dart';
void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
home: PlayerApp(),
),
);
}
class PlayerApp extends StatefulWidget {
const PlayerApp({super.key});
#override
State<PlayerApp> createState() => _PlayerAppState();
}
class _PlayerAppState extends State<PlayerApp> with TickerProviderStateMixin {
AnimationController? _controller;
Animation? _waveAnim;
Animation? _waveConstAmpAnim;
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 20))
..addListener(() => setState(() {}));
_waveAnim = Tween<double>(begin: 1, end: 1).animate(_controller);
_waveConstAmpAnim = Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(curve: Curves.easeInSine, parent: _controller));
_controller!.forward(); //null safe 6:32
}
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
return Scaffold(
body: Stack(
children: <Widget>[
Positioned(
height: height,
width: width,
child: Material(
elevation: 16,
color: const Color(0xFFd6dde5), //Background Color
borderRadius: BorderRadius.circular(20),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0,
),
child: Column(
children: <Widget>[
const SizedBox(
height: 90,
),
const Text(
'Music title',
),
const SizedBox(
height: 15,
),
const Text(
'Music artist',
),
const SizedBox(
height: 75,
),
buildRecordPlayer(),
const SizedBox(
height: 60,
),
Row(
children: <Widget>[
const Text('time'),
const SizedBox(
width: 8,
),
buildWave(width),
const SizedBox(
width: 8,
),
const Text('end'),
],
)
],
),
),
),
)
],
),
);
}
Widget buildRecordPlayer() {
return Container(
height: 270,
width: 270,
alignment: Alignment.center,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/vinyl.png'),
fit: BoxFit.fitHeight,
colorFilter: ColorFilter.mode(
Colors.blue,
BlendMode.color,
),
),
shape: BoxShape.circle,
),
child: ClipOval(
child: Image.asset(
'assets/images/SL.png',
height: 165,
width: 165,
fit: BoxFit.fill,
),
),
);
}
Widget buildWave(double width) {
return SizedBox(
width: 260 * _waveAnim.value,
height: 40,
child: CustomPaint(
painter: WaveBasePainter(),
child: ClipRect(
clipper: WaveClipper(_waveConstAmpAnim.value * width),
child: CustomPaint(
painter: WaveBasePainter(),
foregroundPainter: WaveColorPainter(_waveAnim),
),
),
),
);
}
}
And this is how my vscode looks like right now. I would be grateful if I could get rid of this error.
I want to create this type of design for my profile page but I really don't know how to create the dashed circle in a flutter.
Create a rounded image or rounded container and then use this plugin dotted_border: ^2.0.0+2
import 'package:flutter/material.dart';
import 'package:dotted_border/dotted_border.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dotted Border'),
),
body: SafeArea(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 8,
children: <Widget>[
rectBorderWidget,
roundedRectBorderWidget,
customBorder,
roundStrokeCap,
solidBorder,
fullWidthPath,
],
),
),
),
),
),
);
}
/// Draw a border with rectangular border
Widget get rectBorderWidget {
return DottedBorder(
dashPattern: [8, 4],
strokeWidth: 2,
child: Container(
height: 200,
width: 120,
color: Colors.red,
),
);
}
/// Draw a border with a rounded rectangular border
Widget get roundedRectBorderWidget {
return DottedBorder(
borderType: BorderType.RRect,
radius: Radius.circular(12),
padding: EdgeInsets.all(6),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(12)),
child: Container(
height: 200,
width: 120,
color: Colors.amber,
),
),
);
}
/// Draw a border with custom path border
Widget get customBorder {
Path customPath = Path()
..moveTo(20, 20)
..lineTo(50, 100)
..lineTo(20, 200)
..lineTo(100, 100)
..lineTo(20, 20);
return DottedBorder(
customPath: (_) => customPath,
color: Colors.indigo,
dashPattern: [8, 4],
strokeWidth: 2,
child: Container(
height: 220,
width: 120,
color: Colors.green.withAlpha(20),
),
);
}
/// Set border stroke cap
Widget get roundStrokeCap {
return DottedBorder(
dashPattern: [8, 4],
strokeWidth: 2,
strokeCap: StrokeCap.round,
borderType: BorderType.RRect,
radius: Radius.circular(5),
child: Container(
height: 200,
width: 120,
color: Colors.red,
),
);
}
Widget get solidBorder {
return DottedBorder(
dashPattern: [4, 3],
strokeWidth: 2,
strokeCap: StrokeCap.round,
child: Container(
color: Colors.green,
height: 200,
width: 120,
),
);
}
Widget get fullWidthPath {
return DottedBorder(
customPath: (size) {
return Path()
..moveTo(0, 20)
..lineTo(size.width, 20);
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(),
),
);
}
}
Or try this
dashed_circle: ^0.0.2
import 'package:flutter/material.dart';
import 'package:dashed_circle/dashed_circle.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Bill_Gates_Buys_Skype_%285707954468%29.jpg/2560px-Bill_Gates_Buys_Skype_%285707954468%29.jpg';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dashed Circle Example',
theme: ThemeData(),
home: Scaffold(
body: Center(
child: DashedCircle(
child: Padding(padding: EdgeInsets.all(6.0),
child: CircleAvatar(
radius: 70.0,
backgroundImage: NetworkImage(url),
),
),
color: Colors.deepOrangeAccent,
)
),
),
);
}
}
I am trying to make a triangle from a custom painter have a rounded corner.
Image on the left is what I have so far and Image on the right is what I am tring to do.
Here's is my code.
class Triangle extends StatelessWidget {
const Triangle({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
painter: MyPainter(),
child: Container(
height: MySize.yMargin(10),
width: MySize.xMargin(20),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(30)),
child: Center(
child: Padding(
padding: const EdgeInsets.only(left: 30.0, bottom: 16),
child: Transform.rotate(
angle: math.pi / 4,
child: Text('New',
style: TextStyle(
color: Colors.white,
fontSize: MySize.textSize(5),
fontWeight: FontWeight.bold,
)))))));
}
}
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final paint = Paint();
paint.color = Colors.yellow;
var path = Path();
path.lineTo(size.width, 0);
path.lineTo(size.height, size.width);
path.close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
You can try to check out this package
try this:
import 'package:vector_math/vector_math.dart' as vector;
child: Container(
color: Colors.yellow,
width: 300,
height: 100,
child: Stack(
children: [
Positioned(
top: -20,
right: -20,
child: Transform.rotate(
angle: vector.radians(45),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Container(
alignment: Alignment.bottomCenter,
height: 50,
width: 50,
color: Color(0xff2DD485),
child: Text('NEW'),
),
),
),
),
],
),
),
#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
"Scrolling Viewww :( ",
style: TextStyle(fontSize: 25),
),
Column(
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
Column(children: [
ListView( <------------------ **Making this Expanded**
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: [
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
],
),
]),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
],
)
],
);
I have tried to implement Expanded to resolved this. However, since it is nested twice, it was quite tricky. Only way that I could have done is just to set the Container() widget with given height.
But, in my real Column() widget, I have an AnimatedContainer that changes with its height. So, I want to find a way that I can do this with Expanded or Flexible.
I'd tried million different combinations. Nothing seems to work. How can I make the ListView that is inside the nested Column expandable?
Did you want to fix two item over ListView?
I implemented your request.
import 'package:flutter/material.dart';
import 'dart:math' as math;
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>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return SafeArea(
child: Container(
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 40,
maxHeight: 40,
child: Container(
color: Colors.white,
child: Text(
"Scrolling Viewww :( ",
style: TextStyle(fontSize: 25),
),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: 100,
width: 100,
color: Colors.blue,
child: Text('box1'),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: 100,
width: 100,
color: Colors.blue,
child: Text('box2'),
),
),
),
];
},
body: Builder(
builder: (BuildContext context) {
final innerScrollController = PrimaryScrollController.of(context);
return SingleChildScrollView(
controller: innerScrollController,
child: Column(
children: [
ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: [
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
],
),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
],
),
);
},
),
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
#required this.minHeight,
#required this.maxHeight,
#required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
#override
double get minExtent => minHeight;
#override
double get maxExtent => math.max(maxHeight, minHeight);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
To avoid the bottom overflow, try wrapping a SingleChildScrollView around the first Column. Additionally you can play around with the mainAxisSize property of the different Columns.
I want to create a drop down menu like the image below, Which is opened by touching and dragging and closing by touching the outside.
before dragging
after dragging
Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false
),
body: Stack(
children: <Widget>[
Container(
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(bottom: Radius.circular(20))
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 40),
child: Divider(
color: Colors.blueGrey[500],
height: 10,
indent: 5,
),
),
Icon(FontAwesomeIcons.angleDoubleDown,size: 15,color: Colors.blueGrey[500],)
],
),
)
],
),
),
Center(child: Text('List View'),)
],
)
)
I want to change the height, but I encounter overflow error!
What is the best way to make this widget?
Can I do this within the AppBar?
You can do this in some ways, but one that came up in mind immediately was to use a CustomPaint widget with your own CustomPainter at the top of a Stack so you can actually keep your other widgets below the scrolled bar.
I've tried to replicate what you've shown on the images but feel free to tweak it to your needs.
const kMinScrollBarHeight = 20.0;
class MyScreen extends StatefulWidget {
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
double _scrollBarOffset = 0.0;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(13, 23, 35, 1.0),
appBar: AppBar(
backgroundColor: const Color.fromRGBO(255, 72, 18, 1.0),
),
body: Stack(children: <Widget>[
GestureDetector(
onVerticalDragUpdate: (tapDetails) => setState(() => _scrollBarOffset = tapDetails.globalPosition.dy),
child: Stack(
children: <Widget>[
Center(
child: Text(
'My screen widgets',
style: TextStyle(color: Colors.white),
),
),
Stack(
children: <Widget>[
Positioned(
bottom: MediaQuery.of(context).size.height -
max(_scrollBarOffset,
MediaQuery.of(context).padding.top + kToolbarHeight + kMinScrollBarHeight),
child: CustomPaint(
painter: MyDraggable(),
child: Container(
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(
size: 100.0,
),
Text('Flutter is awesome'),
],
),
),
),
),
],
),
],
),
),
]),
);
}
}
class MyDraggable extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()..color = Colors.white;
final Radius cornerRadius = Radius.circular(20.0);
final double lineMargin = 30.0;
// Draw slider
canvas.drawRRect(
RRect.fromLTRBAndCorners(0.0, 0.0, size.width, size.height,
bottomLeft: cornerRadius, bottomRight: cornerRadius),
paint);
paint.color = Colors.black.withAlpha(64);
paint.strokeWidth = 1.5;
// Draw triangle
canvas.drawPoints(
PointMode.polygon,
[
Offset((size.width / 2) - 5.0, size.height - 10.0),
Offset((size.width / 2) + 5.0, size.height - 10.0),
Offset((size.width / 2), size.height - 5.0),
Offset((size.width / 2) - 5.0, size.height - 10.0),
],
paint);
// Draw line
canvas.drawLine(Offset(lineMargin, size.height - kMinScrollBarHeight),
Offset(size.width - lineMargin, size.height - kMinScrollBarHeight), paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}