I'm wondering what the best approach could be to achieve the effect of the rounded icon button on the bottom right.
Do notice the icon is transparent and reveals the image background.
I tried using the Stack widget, but I could not position it properly nor get the color to be transparent.
Currently I have this:
class Banner extends StatelessWidget {
final String src;
const Banner(this.src, {Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 16 / 9,
child: Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
child: Stack(
children: <Widget>[
Image.network(src),
LayoutBuilder(
builder: (context, constraints) {
var calculatedOverlay = constraints.maxHeight / 3;
return Align(
alignment: Alignment.bottomRight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(calculatedOverlay),
),
color: Colors.white,
),
height: calculatedOverlay,
width: calculatedOverlay,
),
);
},
),
],
),
),
Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
),
),
]),
);
}
}
Which results in this:
Thanks in advance.
Related
When I use Transform.rotate to make a horizontal ListView diagonal as shown below, it becomes diagonal, but the left and right edges are cut off.
Is there a way to display without clipping the left and right edges, or is there a widget that can be used for that?
I came up with a way to use the Stack widget to overlay the left and right edges with strips of gradation and make them invisible.
I've actually tried it and it's fine, but I thought I'd ask if there is another way.
I think this is happening because the screen width is passed from the parent as a constraint, but is there any way to disable the constraint?
Thank you.
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Icons',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.greenAccent,
body: Column(
children: [
Expanded(
child: Center(
child: SizedBox(
width: double.infinity,
height: 200.0,
child: Transform.rotate(
angle: -math.pi / 20,
child: Container(
color: Colors.white,
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 6,
itemBuilder: (context, innerIndex) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
//padding: EdgeInsets.all(4.0),
height: 50.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color:
Colors.red.withOpacity(1.0 - 0.1 * innerIndex),
),
child:Center(child:Text(innerIndex.toString()),),
),
),
),
),
),
),
),
),
Container(
height:100.0,
color: Colors.white,
child:Center(
child:Text('title'),
),
)
],
),
);
}
}
With the following code using OverflowBox, the left and right corners are no longer cut off.
Expanded(
child: Center(
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width*1.2,
child: Transform.rotate(
angle: -math.pi / 20,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 6,
itemBuilder: (context, innerIndex) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
//padding: EdgeInsets.all(4.0),
height: 50.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color:
Colors.red.withOpacity(1.0 - 0.1 * innerIndex),
),
child:Center(child:Text(innerIndex.toString()),),
),
),
),
),
),
),
),
),
How to create Hexagon shape Container with flutter same this photo
It can be archived by using Stack and Container's decoration using bottomLeft.
class AWT extends StatefulWidget {
AWT({Key? key}) : super(key: key);
#override
_AWTState createState() => _AWTState();
}
class _AWTState extends State<AWT> {
final border = const BorderRadius.only(
bottomLeft: Radius.circular(140),
);
clickTest(int index) => OutlinedButton(
onPressed: () {
print("tap Event from $index");
},
child: Text("Click test"));
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.pink.shade100,
elevation: 0,
),
body: LayoutBuilder(
builder: (context, constraints) {
final boxheight = constraints.maxHeight / 6;
return Stack(
children: [
//4th container
Container(
height: (boxheight * 4) + kToolbarHeight,
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: border,
),
child: clickTest(4),
), //3rd container
Container(
height: (boxheight * 3) + kToolbarHeight,
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: border,
),
child: clickTest(3),
), //second container
Container(
height: (boxheight * 2) + kToolbarHeight,
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: Colors.pink.shade300,
borderRadius: border,
),
child: clickTest(2),
),
// top container
Container(
alignment: Alignment.bottomCenter,
height: boxheight,
decoration: BoxDecoration(
color: Colors.pink.shade100,
borderRadius: border,
),
child: clickTest(1),
),
],
);
},
),
);
}
}
What is the best way to get a responsive svg image, I thought about using MediaQuery, but probably not quite it will fit for every screen.
I used Stack and Positioned because I have more things to lay on one screen that will overlap.
I want to make responsive this:
class Shape extends StatelessWidget {
static Route route() {
return MaterialPageRoute<void>(builder: (_) => Shape());
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
),
body: _profilePage(context),
);
}
Widget _profilePage(BuildContext context) {
return SafeArea(
child: Align(
child: Center(
child: Stack(children: <Widget>[
Positioned(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height,
top: MediaQuery.of(context).size.width * 0.4,
child: _curved(context),
),
]),
),
),
);
// });
}
Widget _curved(BuildContext context) {
return SvgPicture.asset(
'assets/images/shape_curved.svg',
color:Colors.green,
allowDrawingOutsideViewBox: true,
);}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
Flexible(
flex: 2,
child: Container(
color: Colors.yellow,
child: Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(80.0),
))),
),
),
Flexible(
child: Container(
color: Colors.green,
child: Container(
decoration: BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(80.0),
))),
),
),
]),
);
}
}
If I just throw together an image and some text in a rounded-corner rectangle, the user will not know that they can "click here". But I don't have to bake my own solution. InkWell covers this scenario, complete with a nice shadow.
I am positioning
a custom clickable icon using the
InkWell
class, itself requiring to be inside an
Ink
instance.
import 'package:flutter/material.dart';
const boat_url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/'
'Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG/'
'182px-Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG');
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Image',
home: Scaffold(
backgroundColor: Colors.grey,
body: MyImage(),
)));
}
class MyImage extends StatelessWidget {
MyImage({Key key,});
#override
Widget build(BuildContext context) {
Size sz = MediaQuery.of(context).size * 0.4;
double border = 4;
return Stack(children: [
Positioned(
top: 100,
left: 100,
width: sz.width,
height: sz.height,
child: Material(
child: Ink(
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
new BoxShadow(
color: Colors.red,
blurRadius: 10.0,
offset: new Offset(30.0, 20.0),
),
],
border: Border.all(
color: Colors.blue,
width: border,
),
borderRadius: BorderRadius.circular(40),
),
child: InkWell(
onTap: (){/*..*/},
child: Column(
children: [
Container(
height: 4 * (sz.height - 2 * border) / 5,
alignment: Alignment.center,
child: Image.network(boat_url),
),
Container(
height: (sz.height - 2 * border) / 5,
child: FittedBox(
clipBehavior: Clip.antiAlias,
alignment: Alignment.centerLeft,
fit: BoxFit.fitHeight,
child: Text('A long descriptive sentence')),
)
],
)),
),
)),
]);
}
}
1- I'm not actually using Colors.white, and the Scaffold itself has
backgroundColor: Colors.grey. Where is the white background coming from?
2- When we talk of a "shadow", I'm expecting the shadow to be behind
the ink/inkwell object. Why does the shadow appear in front?
Related: 1
That white color is from the Material widget, to remove that you can use type param.
Material(
type: MaterialType.transparency,
child: Container(),
);
Here is code to achieve the custom button
Video link
Scaffold(
backgroundColor: Colors.blueGrey,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.green.shade200,
border: Border.all(color: Colors.green),
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
blurRadius: 5,
spreadRadius: 2,
color: Colors.black26,
)
]),
margin: const EdgeInsets.all(20),
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
splashColor: Colors.black26,
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Image.asset(
'assets/images/marked_tyre_base.png',
fit: BoxFit.cover,
width: 80,
height: 80,
),
const SizedBox(
height: 10,
),
Text(
'Tyre 1',
style: TextStyle(color: Colors.white),
)
]),
),
),
),
),
),
),
);
Screenshot:
Create a class, ImageTextButton:
class ImageTextButton extends StatelessWidget {
final VoidCallback onPressed;
final ImageProvider image;
final double imageHeight;
final double radius;
final Widget text;
ImageTextButton({
#required this.onPressed,
#required this.image,
this.imageHeight = 200,
this.radius = 28,
#required this.text,
});
#override
Widget build(BuildContext context) {
return Card(
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: onPressed,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Ink.image(
image: image,
height: imageHeight,
fit: BoxFit.cover,
),
SizedBox(height: 6),
text,
SizedBox(height: 6),
],
),
),
);
}
}
Usage:
ImageTextButton(
onPressed: () {},
image: AssetImage('chocolate_image'),
text: Text('Chocolate'),
)
I am pretty new to flutter and trying to achieve a dismissible bar for my modalSheet. Something like this image:
I can only think of a stack. But that would make the code complex. Please let me know if there is a better way.
Is this what you are looking for modal_bottom_sheet:
showBarModalBottomSheet(
expand: true,
context: context,
backgroundColor: Colors.transparent,
builder: (context, scrollController) =>
ModalInsideModal(
scrollController: scrollController),
)),
To display showModalBottomSheet as IOS modal style:
1- Create new Dart Class IOSModalStyle with this full code:
import 'package:flutter/material.dart';
class IOSModalStyle extends StatelessWidget {
final Widget childBody;
const IOSModalStyle({
Key? key,
required this.childBody,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(16.0),
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_dividerWidget(),
Container(
decoration: BoxDecoration(
color: Colors.white, // color of card
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
),
height: 200, // body container height
width: double.infinity,
child: childBody,
)
],
),
);
}
Widget _dividerWidget() {
return FractionallySizedBox(
widthFactor: 0.2, // width of top divider bar
child: Container(
margin: const EdgeInsets.symmetric( // margin of top divider bar
vertical: 12.0,
),
child: Container(
height: 5.0,
decoration: BoxDecoration(
color: Colors.white, // color of top divider bar
borderRadius: const BorderRadius.all(Radius.circular(2.5)),
),
),
),
);
}
}
2- You can call above class from anywhere like this:
showModalBottomSheet<void>(
isScrollControlled: true, // to full height
useSafeArea: true, // to show under status bar
backgroundColor: Colors.transparent, // to show BorderRadius of Container
context: context,
builder: (BuildContext context) {
return IOSModalStyle(
childBody: Center(
child: Text('Hello, Im Anas...'),
),
);
},
);
Result: