I'm trying to design in Flutter. I don't know how to design this arrow in container.
You can use CustomPainer or ClipPath for this. You can also check this answer for this kind of layout.
class PriceTagPaint extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.red
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill;
Path path = Path();
path
..lineTo(size.width * .85, 0) // .85 amount of right gap
..lineTo(size.width, size.height / 2)
..lineTo(size.width * .85, size.height)
..lineTo(0, size.height)
..lineTo(0, 0)
..close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
And use
SizedBox(
height: 100,
width: 250,
child: CustomPaint(
painter: PriceTagPaint(),
child: Align(
alignment: Alignment(-.2, 0), //litle left
child: Text(
"-11% Off",
style: TextStyle(
fontSize: 44,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
),
),
Result
More about CustomPaint
Related
I would like the row (containing the green and the red widgets) or the green widget to take the red widget's height, but without using a fixed size or a ratio anywhere.
The red widget must impose its size which depends on its content.
Is it possible (in a simple way) ?
image
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: Row(
children: [
Expanded(child: MyContainer(color: Colors.red, child: Column(children: generateTexts(10)))),
Expanded(child: MyContainer(color: Colors.green, child: ListView(children: generateTexts(50))))
],
),
),
Expanded(child: MyContainer(color: Colors.blue, child: Center(child: Text('REMAINING HEIGHT OF THE COLUMN')))),
MyContainer(
height: 50,
color: Colors.yellow,
child: Center(child: Text('FIXED HEIGHT')),
)
],
));
}
}
List<Widget> generateTexts(int count) {
return List<Widget>.generate(count, (index) => Text('text $index'));
}
class MyContainer extends StatelessWidget {
const MyContainer({this.child, this.color = Colors.transparent, this.width, this.height});
final Widget? child;
final Color color;
final double? width;
final double? height;
#override
Widget build(BuildContext context) {
return Container(
child: child,
decoration: BoxDecoration(
color: color, border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(12)),
width: width,
height: height);
}
}
This is my code, I am passing the "Keyname" to the stateless widget, this widget is wrapped with Flexible widget in a different dart file.
I am getting this error:
The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.
Here is the code:
Flexible(
flex: 2,
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
KeyBoardButtonFirstRow(
width: deviceWidth / 6,
color: Color(0xfffdc40d),
keyName: '2nF',
),
KeyBoardButtonFirstRow(
width: deviceWidth / 6,
color: Color(0xff52e2fe),
),
KeyBoardButtonFirstRow(
width: deviceWidth / 2,
color: Color(0xffabbfc5),
),
],
),
class KeyBoardButtonFirstRow extends StatelessWidget {
final String keyName;
final double width;
final Color color;
KeyBoardButtonFirstRow({this.keyName, this.width, this.color});
#override
Widget build(BuildContext context) {
return Container(
height: 30.0,
width: width,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(10.0),
boxShadow: [BoxShadow(
color: Colors.white.withOpacity(0.5),
blurRadius: 2.0,
)],
),
child: Text(keyName),
);
}
}
These are the changes you you need to make to your code,
class Test0 extends StatefulWidget {
#override
_Test0State createState() => _Test0State();
}
class _Test0State extends State<Test0> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Flexible(
flex: 2,
child: Container(
height: MediaQuery.of(context).size.width,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
KeyBoardButtonFirstRow(
width: MediaQuery.of(context).size.width / 6,
color: Color(0xfffdc40d),
keyName: '2nF',
),
],
)
])
))
],
),
);
}
}
class KeyBoardButtonFirstRow extends StatelessWidget {
final String keyName;
final double width;
final Color color;
KeyBoardButtonFirstRow({this.keyName, this.width, this.color});
#override
Widget build(BuildContext context) {
return Container(
height: 30.0,
width: width,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.5),
blurRadius: 2.0,
)
],
),
child: Text(keyName),
);
}
}
Here I have Scaffold, in your case, it could be any constrained widget.
I made a Login screen,
want to Launch camera(font) on click of Activate Button , then how to show the capture image in next page?
I am done with the camera open part , onPressed of Activate Button and also done routing to the next page
----> that's mean in my case Activate button , doing 2 things--> (1) its captured image and (2) going to the next page
Now how can I Show the Capture image in next page which I routing with loginPage Activate button
class LoginFormState extends State<LoginForm> {
File imagefile;
_openCamera(BuildContext context)async{
var picture = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
imagefile = picture;
});
}
showImage(){
if(imagefile == null){
return Text("No Image selected here");
}else {
Image.file(imagefile,width:400,height:400);
}
}
var textLength = 6;
var mobileLength = 10;
#override
Widget build(context) {
return Container(
margin: EdgeInsets.only(
top: 0.0,
right: 43.0,
left: 43),
child: Column(
children: [
userField(),
Container(margin: EdgeInsets.only(top: 40.0)),
numberField(),
Container(margin: EdgeInsets.only(top: 60.0, )),
activateButton(),
Container(margin: EdgeInsets.only(top: 60.0, )),
showImage(),
],
),
);
}
Widget activateButton() {
return RaisedButton(
color: Color(0xFFF4D3AE),
child: Text('Activate',
style: TextStyle(
fontFamily: 'Californian FB',
color: Colors.black, //Color(0xFF425c5a),
fontWeight: FontWeight.normal, //bold
letterSpacing: 2.0,
fontSize: 17.0,
)),
padding: EdgeInsets.symmetric(
horizontal: 75.0,
vertical:
15.0), //Activate button box will take more space horizontally & vertically.
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
topRight: Radius.circular(20),
topLeft: Radius.circular(20),
),
),
onPressed: () {
_openCamera(context);
Navigator.of(context).pushNamed("/CameraAccess");
},
);
}
}
----------------------- This is my second page code:-----------------------------------
import 'package:flutter/material.dart';
class CameraAccess extends StatefulWidget{
#override
createState() {
return CameraAccessState();
}
}
class CameraAccessState extends State<CameraAccess>{
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF425c5a),
body: ListView(
children: <Widget>[
Center(
child: Container(child:
Text('Your Image here',
style: TextStyle(
fontFamily: 'Californian FB',
color: Colors.black, //Color(0xFF425c5a),
fontWeight: FontWeight.normal, //bold
letterSpacing: 2.0,
fontSize: 27.0,
)
),
),
),
]
)
);
}
}
I'm trying to implement a credit card reader (using some API). For the user to take a picture of the card, I'm presenting the camera preview widget full screen. I would like to mask out an area so the user centers the card there.
He're an illustration of what I have in mind
I was wondering how this masking could be accomplished in flutter? Currently I'm just drawing a BoxDecoration, but that's missing the semi transparent, greyed out area.
Container(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.width * 0.8 / 1.55,
decoration: new BoxDecoration(
border: Border.all(
color: Colors.white,
width: 2.0,
style: BorderStyle.solid),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(4.0))),
)
You can try something like this for the time being but it is a very inefficient solution and I am sure there must be a better solution that I too would like to know.
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return Container(
height: MediaQuery.of(context).size.height,
child: Stack(
children: <Widget>[
CustomPaint(
foregroundPainter: P(),
child: CameraPreview(controller),
),
ClipPath(
clipper: Clip(),
child: CameraPreview(controller)),
],
),
);
}
class P extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
canvas.drawColor(Colors.grey.withOpacity(0.8), BlendMode.dstOut);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
class Clip extends CustomClipper<Path>{
#override
getClip(Size size) {
print(size);
Path path = Path()
..addRRect(RRect.fromRectAndRadius(Rect.fromLTWH(10, size.height/2-120, size.width-20, 240), Radius.circular(26)));
return path;
}
#override
bool shouldReclip(oldClipper) {
// TODO: implement shouldReclip
return true;
}
}
I now just went with a custom BoxPainter and first draw the background, then the card area and finally blend the layers together to 'cut out' the center part.
import 'package:flutter/widgets.dart';
class CardDecoration extends Decoration {
#override
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _CardPainter();
}
}
class _CardPainter extends BoxPainter {
#override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final clearPaint = new Paint()
..color = Colors.black
..style = PaintingStyle.fill
..blendMode = BlendMode.dstOut;
final bgPaint = new Paint()
..color = Color.fromARGB(150, 0, 0, 0)
..style = PaintingStyle.fill;
final borderPaint = new Paint()
..color = Colors.white.withAlpha(120)
..style = PaintingStyle.stroke
..strokeWidth = 3.0;
final rect = offset & configuration.size;
final cardWidth = 0.8*rect.width;
final cardHeight = cardWidth/1.55;
canvas.saveLayer(Rect.fromLTRB(0, 0, rect.width, rect.height), clearPaint);
canvas.drawPaint(bgPaint);
canvas.saveLayer(Rect.fromLTRB(0, 0, rect.width, rect.height), clearPaint);
canvas.drawRRect(RRect.fromLTRBR(0.1*rect.width, (rect.height-cardHeight)/2, 0.9*rect.width, (rect.height+cardHeight)/2, Radius.circular(8)), bgPaint);
canvas.restore();
canvas.restore();
canvas.drawRRect(RRect.fromLTRBR(0.1*rect.width, (rect.height-cardHeight)/2, 0.9*rect.width, (rect.height+cardHeight)/2, Radius.circular(8)), borderPaint);
}
}
Probably, you can try with columns, rows, and containers :).
Widget getMaskCard(BuildContext context) {
Color _background = Colors.grey.withOpacity(0.2);
return Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: 1,
color: _background,
),
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width * 0.8,
child: Column(
children: <Widget>[
Expanded(
child: Container(
color: _background,
),
),
Container(
height: 180,
width: MediaQuery.of(context).size.width * 0.8,
color: Colors.transparent,
),
Expanded(
child: Container(
color: _background,
),
),
],
),
),
Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: 1,
color: _background,
),
),
],
)
],
);
}
Example
I have a layout effect, I don't know how to implement it more easily? I have six or N child widgets, placed in a parent widget with two child widgets per row, each widget is 50% the width of the parent widget and height is the height /rows of the parent widget.
I can use column, row expanded to do this, but I don't think it's simple enough.If my child widgets are intermediate, I don't know how to create them dynamically.
The layout effect what I want to achieve:
The way I want to do it is the following pseudocode
I can do it in Android and iOS, but I don't know how to do it with flutter.
var parentWidget = Widget()
for (var i = 0; i < 6; i++) {
var child = Widget()
parentWidget.add(child)
}
The Flutter is implemented as follows. I can use column,row expanded to do this, but I don't think it's simple enough. If my child widgets are indeterminate, I don't know how to create them dynamically.
Expanded(
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Row(children: <Widget>[
Expanded(child: Text("1"),),
Expanded(child: Text("1"),),
],)
),
Expanded(
flex: 1,
child:Row(children: <Widget>[
Expanded(child: Text("1"),),
Expanded(child: Text("1"),),
],),
),
Expanded(
flex: 1,
child: Row(children: <Widget>[
Expanded(child: Text("1"),),
Expanded(child: Text("1"),),
],),
)
],
),
)
I've come up with a way to deal with this requirement by calculating the width and height of each child widget and then placing them in wrap to arrange themselves
class RowFixedWrap extends StatefulWidget {
final double spacing;
final double runSpacing;
final int columnCount;
final List<Widget> childern;
RowFixedWrap(
{Key key, this.spacing, this.runSpacing, this.columnCount, this.childern})
: super(key: key);
#override
State<StatefulWidget> createState() {
return _FixedWrapState();
}
}
class _FixedWrapState extends State<RowFixedWrap> {
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
var itemWidth =
(constraints.maxWidth - widget.spacing * (widget.columnCount - 1)) /
widget.columnCount;
var rows = widget.childern.length % widget.columnCount != 0
? (widget.childern.length ~/ widget.columnCount) + 1
: (widget.childern.length ~/ widget.columnCount);
var itemHeight =
(constraints.maxHeight - widget.runSpacing * (rows - 1)) / rows;
return Wrap(
spacing: widget.spacing,
runSpacing: widget.runSpacing,
children: widget.childern.map((widget) {
return SizedBox(
width: itemWidth,
height: itemHeight,
child: widget,
);
}).toList());
},
);
}
}
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: RowFixedWrap(
spacing: 10,
runSpacing: 10,
columnCount: 2,
childern: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.red,
),
Container(
color: Colors.red,
),
Container(
color: Colors.red,
),
],
),
));