Hello Guys I would like to ask is it possible to achieve this kind of design using code? I really got stuck, here is design I would like to achieve
but the real problem is I only achieve this
this is my sample code:
in my main:
return Scaffold(
backgroundColor: Color(0xff012a60),
body: Stack(children: <Widget>[
/*_AnimatedCircle(
outerController: outerController,
innerController: innerController,
),*/
_OuterCircle(circleColor: Colors.blueGrey[900].withOpacity(.8)),
Column(children: <Widget>[
const Spacer(flex: 50),
Expanded(flex: 30, child: Container(color: Colors.white)),
const Spacer(flex: 20),
]),
Row(children: <Widget>[
const Spacer(flex: 80),
Transform.scale(
scale: 2.5,
child: Container(
width: MediaQuery.of(context).size.width * 0.2,
decoration: const BoxDecoration(
color: Colors.red, shape: BoxShape.circle)),
),
]),
// _OuterCircle(circleColor: Colors.blueAccent.withOpacity(.25)),
Row(children: <Widget>[
const Spacer(flex: 80),
Column(children: [
Spacer(flex: 60),
Transform.scale(
scale: 2.5,
child: Container(
width: MediaQuery.of(context).size.width * 0.2,
height: MediaQuery.of(context).size.width * 0.05,
decoration: const BoxDecoration(color: Colors.green)),
),
Spacer(flex: 24),
]),
]),
]),
);
and this is my other class
class _OuterCircle extends StatelessWidget {
const _OuterCircle({Key key, this.circleColor}) : super(key: key);
final Color circleColor;
#override
Widget build(BuildContext context) {
return Transform.scale(
scale: 2,
child: Container(
width: MediaQuery.of(context).size.width * 0.47,
decoration: BoxDecoration(shape: BoxShape.circle, color: circleColor),
));
}
}
Please help I really stuck how to achieve this kind of design in dart code
I think it is easier to break down the geometry problem from the largest area to small area.
The key point of achieve this is using Clip (ClipOval, ClipRect...)
The upper part can be draw by using right circle to clip left circle
The lower part can be draw by using right circle to clip inner rectangle
Scale the stack area
Draw large left circle (area 1)
Draw middle white rectangle (area 2)
Draw right circle with rectangle inside (area 3)
Draw the middle intersection part (area 4)
Widgets in used: ClipOval, FractionallySizedBox, AspectRatio,
The left Big Circle
class BigCircle extends StatelessWidget {
const BigCircle({this.color,Key key}):super(key: key);
final Color color;
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1,
child: Container(
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
),
);
}
}
The custom oval clipper (clip right white circle area)
class CustomClipOval extends CustomClipper<Rect> {
#override
Rect getClip(Size size) {
final width = size.width * 0.42;
return Rect.fromLTRB(
size.width - width,
(size.height - width) * 0.5,
size.width,
(size.height + width) * 0.5,
);
}
#override
bool shouldReclip(covariant CustomClipper<Rect> oldClipper) {
return false;
}
}
Finally the stack
return Scaffold(
backgroundColor: const Color(0xff004471),
body: Transform.scale(
scale: 1.19,
child: Stack(children: <Widget>[
// Area 1
const Align(
alignment: Alignment.centerLeft,
child: BigCircle(
color: Color(0xff022c66),
),
),
// Area 2
Align(
alignment: const Alignment(0, 0.4),
child: FractionallySizedBox(
heightFactor: 0.23,
child: Container(
color: Colors.white,
),
),
),
// Area 3
ClipOval(
clipper: CustomClipOval(),
child: Container(
alignment: const Alignment(0, 0.46),
color: Colors.white,
child: FractionallySizedBox(
heightFactor: 0.14,
child: Container(
color: const Color(0xff335f86),
),
),
),
),
// Area 4
ClipOval(
clipper: CustomClipOval(),
child: const Align(
alignment: Alignment.centerLeft,
child: BigCircle(color: Color(0xff647294),),
),
),
]),
),
);
Related
There is a card widget. As seen in the picture, I want lines on this card widget. But I don't know how to do this. I would be glad if you could help me with this.
Problem Solved!
This Card Widget Code
Container(
height: 190.sp, //
width: 360.sp,
padding: EdgeInsets.symmetric(horizontal: 5.sp),
child: Card(
color: Colors.orange,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
child: Stack(
children: [
Align(
alignment: Alignment.bottomRight,
child: Transform.rotate(
angle: -pi / 2,
child: CustomPaint(
painter: MyPainter(),
child: SizedBox(width: 65, height: 65),
),
),
),
Align(
alignment: Alignment.bottomRight,
child: Transform.rotate(
angle: -pi / 2,
child: Transform.translate(
offset: Offset(25, 0),
child: CustomPaint(
painter: MyPainter(),
child: SizedBox(width: 30, height: 30),
),
),
),
),
],
),
));
THIS CUSTOM PAINTER
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final redCircle = Paint()
..color = Colors.white
..style = PaintingStyle.stroke;
final arcRect = Rect.fromCircle(
center: size.bottomCenter(Offset.zero), radius: size.shortestSide);
canvas.drawArc(arcRect, 0, -pi, false, redCircle);
}
#override
bool shouldRepaint(MyPainter oldDelegate) => false;
}
I'm creating a online shop store, at the moment I have basically finished most of it. Currently I'm developing the credit card animation, althought I had some problems with the text. I had problems when rotating it, it semmed it has to be rotated in 180 degres.
The back of my card is showing the number the wrong format.
This is how I set up the main page:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:loja_virtual_nnananene/screens/checkout/card/card_back.dart';
import 'package:loja_virtual_nnananene/screens/checkout/card/card_front.dart';
class CardTile extends StatefulWidget {
#override
_CardTileState createState() => _CardTileState();
}
class _CardTileState extends State<CardTile> {
double horizontalDrag = 0;
#override
Widget build(BuildContext context) {
return GestureDetector(
onHorizontalDragUpdate: (horizontal) {
setState(() {
horizontalDrag += horizontal.delta.dx;
horizontalDrag %= 360;
});
},
child: Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.0001)
..rotateY(pi / 180 * horizontalDrag),
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.fromLTRB(16, 10, 16, 16),
width: 240,
height: 240,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey,
gradient: LinearGradient(
colors: [Color(0xff323232), Color(0xff000000)],
begin: Alignment.topLeft,
end: Alignment.bottomRight)),
child: horizontalDrag <= 90 || horizontalDrag >= 270
? CardFront()
: CardBack(),
),
),
);
}
}
The card back:
import 'package:flutter/material.dart';
class CardBack extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 18),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
height: 50,
color: Colors.grey[700],
),
SizedBox(
height: 10,
),
Container(
margin: EdgeInsets.fromLTRB(0, 0, 20, 0),
height: 40,
width: 220,
color: Colors.grey[700],
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text('123'.split('').reversed.join('')),
)),
),
],
),
);
}
}
You could just rotate the entire back of the card. You can wrap the root Container in CardBack with a Transform, and flip it, or just transform CardBack.
Transform(
alignment: FractionalOffset.center,
transform: Matrix4.identity..rotateY(pi),
child: CardBack(),
),
I would like to render something that looks a bit like a scrollbar to indicate that I am on page 2/5. To do this, I would need a widget with the following:
The width is 20% width relative to the size of the parent
Top-left of the widget is offset by 40% relative to the size of the parent
I was able to accomplish the first point using a FractionallySizedBox but I'm not sure how to compose this to accomplish the offset. Thanks!
Here is a Flutter codepen illustrating what I have so far. I would like to offset this by 40% relative to the parent while still preserving the 20% width.
https://codepen.io/venkatd-the-bashful/pen/jOWYQXz
Snippet of the example below
class PagePositionDisplay extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 30,
width: 300,
child: Container(
color: Colors.grey,
child: FractionallySizedBox(
alignment: Alignment.topLeft,
heightFactor: 1,
widthFactor: 0.2,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.blue,
),
),
),
),
),
),
);
}
}
Try using Layout Builder with some row:
class PagePositionDisplay extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 30,
width: 300,
child: Container(
color: Colors.grey,
child: LayoutBuilder(builder: (context, constraints) {
return Row(
children: <Widget>[
SizedBox(
// your offset percentage * total width
width: (2 / 5) * constraints.maxWidth,
),
Container(
// your 'scrollbar' percentage * total width
width: (1 / 5) * constraints.maxWidth,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.blue,
),
),
],
);
}),
),
),
),
);
}
}
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;
}
In flutter, is it possible to place a part of a card on another container? In CSS, we would set margin-top to a negative value or use translate property. In flutter as we cannot set negative values to margin-top, is there an alternative to that?
Yes, you can acheive it with a Stack widget. You can stack a card over the background and provide a top or bottom padding.
A simple example would look like:
class StackDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
// The containers in the background
new Column(
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height * .65,
color: Colors.blue,
),
new Container(
height: MediaQuery.of(context).size.height * .35,
color: Colors.white,
)
],
),
// The card widget with top padding,
// incase if you wanted bottom padding to work,
// set the `alignment` of container to Alignment.bottomCenter
new Container(
alignment: Alignment.topCenter,
padding: new EdgeInsets.only(
top: MediaQuery.of(context).size.height * .58,
right: 20.0,
left: 20.0),
child: new Container(
height: 200.0,
width: MediaQuery.of(context).size.width,
child: new Card(
color: Colors.white,
elevation: 4.0,
),
),
)
],
);
}
}
The output of the above code would look something like:
Hope this helps!
Screenshot:
Instead of hardcoding Positioned or Container, you should use Align.
Code:
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: [
Column(
children: [
Expanded(flex: 2, child: Container(color: Colors.indigo)),
Expanded(child: Container(color: Colors.white)),
],
),
Align(
alignment: Alignment(0, 0.5),
child: Container(
width: size.width * 0.9,
height: size.height * 0.4,
child: Card(
elevation: 12,
child: Center(child: Text('CARD', style: Theme.of(context).textTheme.headline2)),
),
),
),
],
),
);
}
Here is running example with overlay:
class _MyHomePageState extends State<MyHomePage> {
double _width = 0.0;
double _height = 0.0;
#override
Widget build(BuildContext context) {
_width = MediaQuery.of(context).size.width;
_height = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: <Widget>[
// The containers in the background and scrollable
getScrollableBody(),
// This container will work as Overlay
getOverlayWidget()
],
),
);
}
Widget getOverlayWidget() {
return new Container(
alignment: Alignment.bottomCenter,
child: new Container(
height: 100.0,
width: _width,
color: Colors.cyan.withOpacity(0.4),
),
);
}
Widget getScrollableBody() {
return SingleChildScrollView(
child: new Column(
children: <Widget>[
new Container(
height: _height * .65,
color: Colors.yellow,
),
new Container(
height: _height * .65,
color: Colors.brown,
),
new Container(
margin: EdgeInsets.only(bottom: 100.0),
height: _height * .65,
color: Colors.orange,
),
],
),
);
}
}
Here is Result of code:
Scrollable Body under customised Bottom Bar