I built a layout but I know this is not good way to create this layout.
so how to get the best approach to create this layout with dynamic and alignment of middle widget should in center .
CODE:
class StartGroupChatScreen extends StatelessWidget {
double startPoint = 30;
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Row(
children: [
IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: MyTheme.secondryColor,
),
onPressed: () {},
),
Text(
"GROUP CHAT",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
color: MyTheme.secondryColor),
),
],
)),
body: Container(
color: MyTheme.grey800,
child: Stack(
children: [
InkWell(
child: Align(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: size.height * 0.14,
alignment: Alignment.center,
child: Stack(
children: [
Positioned(
left: startPoint,
child: UserAvatar(
imageUrl:
"https://wallpaperaccess.com/full/3957694.jpg",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 30,
child: UserAvatar(
imageUrl:
"https://m.media-amazon.com/images/M/MV5BZDA1ODgyODEtOWI3Yy00N2UzLTk5ZGMtZGI1MzU5YzFkZDQ1XkEyXkFqcGdeQXVyMTc4MzI2NQ##._V1_UY1200_CR285,0,630,1200_AL_.jpg",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 60,
child: UserAvatar(
imageUrl:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhS1n9AgNPFrsPjj0fHqwPdIJPJLl9hXUq5Q&usqp=CAU",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 90,
child: UserAvatar(
imageUrl:
"https://img.mensxp.com/media/content/2020/Aug/Michele-Morrone-From-365-Days-Floored-Us-With-His-Fashion-Game-1200x900_5f2a761253b66_1200x900.jpeg",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 120,
child: UserAvatar(
imageUrl:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS44UpSZW-GZwDVxU3763H9HPOWqdB6ThRAoQ&usqp=CAU",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 150,
child: UserAvatar(
imageUrl:
"https://img1.nickiswift.com/img/gallery/the-untold-truth-of-michele-morrone-from-365-days/intro-1593017194.jpg",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 180,
child: UserAvatar(
imageUrl:
"https://images2.minutemediacdn.com/image/upload/c_fill,w_720,ar_16:9,f_auto,q_auto,g_auto/shape/cover/sport/Bar-Giuseppe-Red-Carpet---14th-Rome-Film-Fest-2019-7de8f118ccdbce430f2d706463c8e09c.jpg",
avatarRadius: size.height * 0.12),
),
Positioned(
left: startPoint + 210,
child: UserAvatar(
imageUrl:
"https://stat2.bollywoodhungama.in/wp-content/uploads/2021/04/Netflixs-365-Days-breakout-star-Michele-Morrone-looks-sharp-on-the-cover-of-Elle-India-..jpg",
avatarRadius: size.height * 0.12),
),
],
),
),
SizedBox(
height: size.height * 0.02,
),
Text(
"START CHAT",
style: TextStyle(
color: MyTheme.white,
fontWeight: FontWeight.bold,
fontSize: 28.0),
),
],
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: InkWell(
onTap: () {},
child: Container(
height: size.height * 0.08,
alignment: Alignment.center,
decoration: BoxDecoration(
color: MyTheme.primaryColor,
),
child: Text(
"CONTINUE",
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 17.0),
),
),
),
)
],
),
),
);
}
}
USER AVATER:
class UserAvatar extends StatelessWidget {
final String imageUrl;
final double avatarRadius;
const UserAvatar({Key key,#required this.imageUrl , #required this.avatarRadius}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: avatarRadius,
width: avatarRadius,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(imageUrl),
fit: BoxFit.cover
)
),
);
}
}
OUTPUT:
dartPad
Actually it was good 👍
But it seems repetitive, i think you should add another field properties like the position of image and also avatar radius because its have same repetitive const value
UserAvatar(
imageUrl: "https://wallpaperaccess.com/full/3957694.jpg",
imageNo : 1,
),
),
So the widget should be like this
class UserAvatar extends StatelessWidget {
final String imageUrl;
final double avatarRadius;
final int imageNo;
const UserAvatar({Key key,#required this.imageUrl , #required this.avatarRadius}) : super(key: key);
#override
Widget build(BuildContext context) {
double startPoint = 30;
final size = MediaQuery.of(context).size;
return Positioned(
left: startPoint + (30 * imageNo),
Container(
height: size.height * 0.12,
width: size.height * 0.12,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(imageUrl),
fit: BoxFit.cover
)
),
),
);
}
}
And moreover actually you can also move the body for the show avatar
from line 37 ~ 100 because it is constant value
Related
I'm trying to make a music app and I'm in trouble with modifying positions of 'Playlist of the week' text and the Listview of the images right now. I want to make those two properties more upwards but I have no idea what to do.
This is my home.dart file
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final PageStorageBucket bucket = PageStorageBucket();
late PageViewHolder holder;
late PageController _controller;
double fraction =
0.57; // By using this fraction, we're telling the PageView to show the 50% of the previous and the next page area along with the main page
#override
void initState() {
super.initState();
holder = PageViewHolder(value: 2.0);
_controller = PageController(initialPage: 2, viewportFraction: fraction);
_controller.addListener(() {
holder.setValue(_controller.page);
});
}
int index = 1;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: const Color.fromARGB(255, 223, 234, 244),
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: const Text('AppBar'),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 30,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist for you',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
const SizedBox(height: 35),
Container(
child: Center(
child: AspectRatio(
aspectRatio: 1,
child: ChangeNotifierProvider<PageViewHolder>.value(
value: holder,
child: PageView.builder(
controller: _controller,
itemCount: 4,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return MyPage(
number: index.toDouble(),
fraction: fraction,
);
}),
),
),
),
),
////Your Playlist of the week text
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
InkWell(
onTap: () {},
child: Ink(
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
'assets/images/album1.jpg',
height: 160.0,
width: 200.0,
),
),
),
),
const SizedBox(
width: 30,
),
InkWell(
onTap: () {},
child: Ink(
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
'assets/images/album2.jpg',
height: 160.0,
width: 200.0,
),
),
),
),
const SizedBox(
width: 30,
),
InkWell(
onTap: () {},
child: Ink(
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
'assets/images/album3.jpg',
height: 160.0,
width: 200.0,
),
),
),
),
const SizedBox(
width: 30,
),
InkWell(
onTap: () {},
child: Ink(
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
'assets/images/album4.jpg',
height: 160.0,
width: 200.0,
),
),
),
),
const SizedBox(
width: 30,
),
InkWell(
onTap: () {},
child: Ink(
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
'assets/images/album5.jpg',
height: 160.0,
width: 200.0,
),
),
),
),
],
),
),
],
),
),
),
],
),
),
),
),
);
}
}
class MyPage extends StatelessWidget {
final number;
final double? fraction;
const MyPage({super.key, this.number, this.fraction});
#override
Widget build(BuildContext context) {
double? value = Provider.of<PageViewHolder>(context).value;
double diff = (number - value);
// diff is negative = left page
// diff is 0 = current page
// diff is positive = next page
//Matrix for Elements
final Matrix4 pvMatrix = Matrix4.identity()
..setEntry(3, 2, 1 / 0.9) //Increasing Scale by 90%
..setEntry(1, 1, fraction!) //Changing Scale Along Y Axis
..setEntry(3, 0, 0.004 * -diff); //Changing Perspective Along X Axis
final Matrix4 shadowMatrix = Matrix4.identity()
..setEntry(3, 3, 1 / 1.6) //Increasing Scale by 60%
..setEntry(3, 1, -0.004) //Changing Scale Along Y Axis
..setEntry(3, 0, 0.002 * diff) //Changing Perspective along X Axis
..rotateX(1.309); //Rotating Shadow along X Axis
return Stack(
fit: StackFit.expand,
alignment: FractionalOffset.center,
children: [
Transform.translate(
offset: const Offset(0.0, -47.5),
child: Transform(
transform: pvMatrix,
alignment: FractionalOffset.center,
child: Container(
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
blurRadius: 11.0,
spreadRadius: 4.0,
offset: const Offset(
13.0, 35.0), // shadow direction: bottom right
)
]),
child: Image.asset(
"assets/images/image_${number.toInt() + 1}.jpg",
fit: BoxFit.fill),
),
),
),
],
);
}
}
And this is the image that I'm expecting right now.
Yeah, I solved it with wrapping the Padding of both text and the ListView with Transform.translate and did some tinkering with the offset.
Thank God I solved this! :)
Try to place a column inside the singlechildscrollview and define mainaxisalignment as min
Set height property of Container widget wrapping PageView.
I have a screen as attached. Stack position is not responsive for low resolution device. So how can I create this screen to fix in any device?
home_Screen.dart
// ignore_for_file: prefer_const_constructors_in_immutables
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:thitsarparami/ui/home/components/menu.dart';
import '../../helper/constants.dart';
import '../../helper/enum.dart';
import '../chanting/chanting_catalog_screen.dart';
import '../monk/monk_screen.dart';
import '../radio/radio_screen.dart';
import '../youtube/video_screen.dart';
import 'components/monk_carousel.dart';
import 'components/myanmar_calender.dart';
class HomeScreen extends StatefulWidget {
static const routeName = '/home';
final BuildContext? menuScreenContext;
final Function? onScreenHideButtonPressed;
final bool hideStatus;
const HomeScreen(
{Key? key,
this.menuScreenContext,
this.onScreenHideButtonPressed,
this.hideStatus = false})
: super(key: key);
#override
HomeState createState() => HomeState();
}
class HomeState extends State<HomeScreen> {
final _itemsView = GlobalKey();
double _stackHeight = 0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
RenderBox stackRB =
_itemsView.currentContext?.findRenderObject() as RenderBox;
setState(() {
_stackHeight = stackRB.size.height;
});
});
}
#override
Widget build(BuildContext context) {
final double screenHeight = MediaQuery.of(context).size.height;
final double screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: SingleChildScrollView(
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
height: screenHeight * 0.7,
child: Container(
padding: const EdgeInsets.only(
top: 30, left: 0, right: 0, bottom: 10),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).primaryColorDark,
Theme.of(context).primaryColor,
Theme.of(context).primaryColorLight,
],
stops: const [
0.0,
0.5,
0.7,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Container(
width: screenWidth * 0.70,
//height: screenHeight * 0.20,
//color: Colors.black,
padding: const EdgeInsets.only(
top: 10, left: 10, right: 0, bottom: 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
kHomeTitle1,
style: Theme.of(context).textTheme.headline1,
),
Text(
kHomeTitle2,
style: Theme.of(context).textTheme.headline2,
),
Text(
kHomeTitle3,
style: Theme.of(context).textTheme.headline3,
),
],
),
),
),
Container(
width: screenWidth * 0.30,
height: screenHeight * 0.15,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/buddha.png"),
fit: BoxFit.contain),
),
),
],
),
Container(
height: screenHeight * 0.15,
padding: const EdgeInsets.only(
top: 0, left: 20, right: 20, bottom: 10),
child: const MyanmarCalender(),
),
],
),
),
),
Positioned(
left: 0,
right: 0,
top: screenHeight * 0.30,
key: _itemsView,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(70),
),
),
child: Column(
children: [
const SizedBox(
height: 10,
),
Row(
children: [
MenuButton(
screenWidth: screenWidth,
iconData: Icons.music_video,
screen: const MonkScreen(
title: kMenuMp3,
screenMode: MonkScreenMode.song,
albumType: AlbumType.dhamatalk,
),
title: kMenuMp3,
),
MenuButton(
screenWidth: screenWidth,
iconData: Icons.play_lesson_rounded,
screen: const MonkScreen(
title: kMenuLecture,
screenMode: MonkScreenMode.lecture,
albumType: AlbumType.lecture,
),
title: kMenuLecture,
),
],
),
Row(
children: [
MenuButtonWithImageIcon(
screenWidth: screenWidth,
assetImage:
const AssetImage('assets/images/book.jpeg'),
screen: const MonkScreen(
title: kMenuEbook,
screenMode: MonkScreenMode.book,
albumType: AlbumType.ebook,
),
title: kMenuEbook,
),
MenuButtonWithImageIcon(
screenWidth: screenWidth,
assetImage:
const AssetImage('assets/images/prayer.png'),
screen: const ChantingCatalogScreen(),
title: kMenuChantig,
),
],
),
Row(
children: [
MenuButton(
screenWidth: screenWidth,
iconData: Icons.video_camera_front_outlined,
screen: const VideoScreen(),
title: kLiveStreaming,
withNavBar: false,
),
MenuButton(
screenWidth: screenWidth,
iconData: Icons.radio,
screen: const RadioScreen(),
title: kOnlineRadio,
),
],
),
const SizedBox(
height: 10,
),
const AutoSizeText(
kLatestDhama,
style: TextStyle(
fontSize: 18,
),
),
const SizedBox(
height: 10,
),
const MonkCarousel(),
],
),
),
),
Container(
height: _stackHeight + (screenHeight * 0.45),
),
],
),
),
);
}
}
iPhone 13 pro max vs iPhone 8
You can use the mediaQuery class which is a built-in component in Flutter to get the user's specifications - height and width etc - and then define some terms to suit their design size
for example:
Container(
width: mediaQuery.of(context).size.width * 0.5,
height: 150,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/buddha.png"),
fit: BoxFit.contain),
In this example we told the container width to take 50% of the screen width on any devise, you can use it wherever you want. you can read more about it in the official docs: https://api.flutter.dev/flutter/widgets/MediaQuery-class.html
You can create static class for size
class AppSize{
static double width=MediaQuery.of(context).size.width;
static double height=MediaQuery.of(context).size.height;
}
if you want use like that
Container(
width: AppSize.width * 0.1 ,
height: AppSize.height * 0.6 ,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/buddha.png"),
fit: BoxFit.contain),
I am currently developing my first flutter-application and I need some help with my onboarding screen.
The top part has a Lottiefile asset in a container. The bottom part has some Buttons.
Is it possible to set the size of the container with the Lottiefile asset in it depending of the size of the bottom part? I do not want to have a scroll view, so everything should fit it one screen. The Lottiefile asset should fill the space between the top and the beginning of the bottom part. Is there any possibility to set the size depending of the width and height of the free space?
I tried to set height & width to double.infinity but that crashed my app.
Here's the code:
class OnBoardingPage extends StatelessWidget {
const OnBoardingPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
toolbarHeight: 0,
elevation: 0,
backgroundColor: AppColor.statusbarColor,
),
backgroundColor: AppColor.statusbarColor,
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // <-- spaceBetween
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: size.width * 0.08),
child: Column(
children: [
SizedBox(
height: size.height * 0.03,
),
Container(
width: double.infinity,
child: Lottie.asset('assets/images/files.json',
fit: BoxFit.cover, repeat: false),
),
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: size.width * 0.08),
child: Column(
children: [
SizedBox(
height: size.height * 0.05,
),
Container(
height: size.height * 0.012,
width: size.width * 0.14,
decoration: BoxDecoration(
color: AppColor.textColor,
borderRadius: BorderRadius.circular(15)),
),
SizedBox(
height: size.height * 0.03,
),
AppText(
title: "...",
color: AppColor.textColor,
size: size.height * 0.024,
),
SizedBox(
height: size.height * 0.015,
),
AppText(
title:
"...",
textAlign: TextAlign.center,
color: AppColor.textColor,
size: size.height * 0.018,
),
SizedBox(
height: size.height * 0.05,
),
AppButton(
buttonName: "Register",
buttonColor: AppColor.buttonColor,
textColor: AppColor.buttonTextColor,
onTap: () {
Get.to(const SignUp());
},
buttonRadius: BorderRadius.circular(15),
buttonWidth: size.width,
fontWeight: FontWeight.w500,
buttonHeight: size.height * 0.065,
),
SizedBox(
height: size.height * 0.02,
),
AppButton(
buttonName: "Login",
buttonColor: AppColor.buttonColor,
textColor: AppColor.buttonTextColor,
onTap: () {
Get.to(const LoginScreen());
},
buttonRadius: BorderRadius.circular(15),
buttonWidth: size.width,
fontWeight: FontWeight.w500,
buttonHeight: size.height * 0.065,
),
SizedBox(
height: size.height * 0.02,
),
InkWell(
onTap: () {
Get.to(const Guest());
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppText(
title: "Continue as a Guest (...)",
color: AppColor.primaryColor,
size: size.height * 0.02,
),
SizedBox(
height: size.height * 0.014,
),
],
),
),
SizedBox(
height: size.height * 0.05,
),
],
),
),
],
));
}
}
I hope somebody is can help me with that problem. Thank you very much.
Did you try wrapping your Column or Container in an Expanded widget?
I was trying to add a border shadow effect to a Container in a way that resembles exactly the same design as in the picture below. My initial idea was of using the CustomPaint class feature to do so. However, it hasn't worked out the way I wanted it to. I would honestly like to know how this can be achieved through the use of the CustomPaint class and I apologize for the code that I've written as I'm still trying to get used to CustomPaint. The code and the pictures are as follows:
This is what I intend to achieve:
This is what I have. You can see that the border goes well beyond where it should be and also, the border at the bottom gets clipped and despite adjusting the bottom padding:
This is the code:
class ProfilePageState extends State<ProfilePage> {
#override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: [SystemUiOverlay.bottom]);
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
final textScale = MediaQuery.of(context).textScaleFactor * 1.2;
// TODO: implement build
return Scaffold(
body: ListView(
children: [
Container(
height: height * 1,
width: width * 1,
// color: Colors.red,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/filter.png'),
fit: BoxFit.cover)),
child: Column(
......
Padding(
padding: EdgeInsets.only(left: width * 0.035),
child: Container(
width: double.infinity,
height: height * 0.25,
padding: EdgeInsets.only(
left: width * 0.03,
top: height * 0.01,
// bottom: height * 0.01
),
// color: Colors.yellow,
child: ProfilePageFavourite(), //This here is the widget
),
),
],
),
),
],
),
);
}
}
The ProfilePageFavourite widget:
class ProfilePageFavouriteState extends State<ProfilePageFavourite> {
// final List<dynamic> _favouritesList = [
// ];
var favourite = false;
void _onPressed() {
setState(() => favourite = !favourite);
print(favourite);
}
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
final textScale = MediaQuery.of(context).textScaleFactor * 1.2;
// TODO: implement build
return ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Stack(
children: [
CustomPaint( //This is where I try using the CustomPaint class
painter: OrangePainter(),
child: Container(
width: width * 0.75,
margin: EdgeInsets.only(right: width * 0.09),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.yellow,
image: DecorationImage(
fit: BoxFit.fitWidth,
image: AssetImage('assets/images/pub screen 1 (1).png'))),
),
),
Positioned(
top: height * 0.16,
child: Container(
height: height * 0.07,
width: width * 0.75,
padding: EdgeInsets.only(top: height * 0.008),
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20))),
child: Column(
children: [
Row(
// mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(left: width * 0.05),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.red,
blurRadius: 35,
spreadRadius: 8,
offset: Offset(0, 2))
]),
child: Image.asset(
'assets/icons/dine.png',
color: Colors.white,
),
),
SizedBox(
width: width * 0.02,
),
Text(
'Sollicitudin',
textScaleFactor: textScale,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20,
shadows: [
Shadow(
color: Colors.red,
blurRadius: 10,
offset: Offset(0, 2))
]),
)
],
),
Container(
width: double.infinity,
// color: Colors.red,
padding: EdgeInsets.only(left: width * 0.118),
child: CustomRatingBar(4.5))
],
),
),
),
Positioned(
left: width * 0.58,
top: height * 0.01,
child: Container(
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.pink,
blurRadius: 80,
spreadRadius: 6,
)
]),
child: !favourite
? IconButton(
onPressed: _onPressed,
icon: Icon(
Icons.favorite,
// color: Color.fromRGBO(247, 180, 230, 0.8),
color: Colors.pink,
size: 50,
))
: IconButton(
onPressed: _onPressed,
icon: Icon(
Icons.favorite_border_outlined,
color: Colors.pink,
size: 50,
)),
),
),
],
),
itemCount: 5,
);
}
}
The CustomPaint Class
class OrangePainter extends CustomPainter {
OrangePainter();
#override
void paint(Canvas canvas, Size size) {
final rrectBorder =
RRect.fromRectAndRadius(Offset.zero & size, Radius.circular(12));
final rrectShadow =
RRect.fromRectAndRadius(Offset(0, 2) & size, Radius.circular(12));
final shadowPaint = Paint()
..color = Colors.lightGreen
..style = PaintingStyle.stroke
..strokeWidth = 3
..maskFilter = MaskFilter.blur(BlurStyle.solid, 20);
canvas.drawRRect(rrectShadow, shadowPaint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
I would like to suggest an alternative approach, Custom Paint is very expensive to use in applications. You could instead wrap your container in a Card() then add your shadowColor: Colors.lightGreen set the **shape: ** to the same as your Container() and you should get the result you desire
I have retained the initial customPaint and used it here.This code combines your ProfilePageState and ProfilePageFavourite to give you the appearance below. I've just built it on my phone's dartpad so you can do the editing so it matches. I included comments:
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
height: 250,
width: double.infinity,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: 5,
separatorBuilder: (ctx, index) => const SizedBox(width: 10),
itemBuilder: (ctx, index) => ClipRRect(
child: CustomPaint(
painter: OrangePainter(),
child: Container(
padding: const EdgeInsets.symmetric(horizontal:10,vertical:15),//increase padding to your liking
width: 350,
decoration: BoxDecoration(
// image: DecorationImage(image: AssetImage('')), add your image here and remove color below
color: Colors.black54,
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: const [
Icon(Icons.favorite, size: 40),
],
),
Row(
children: [
const Icon(Icons.restaurant),
const SizedBox(width:10),
Column(
children: const [
Text(
'Sollicitudin',
// textScaleFactor: textScale,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20,
shadows: [
Shadow(
color: Colors.red,
blurRadius: 10,
offset: Offset(0, 2))
],
),
),
Icon(Icons.star),//Replace with your CustomRation()
],
),
],
),
],
),
),
),
),
),
),
);
}
}
class OrangePainter extends CustomPainter {
OrangePainter();
#override
void paint(Canvas canvas, Size size) {
final rrectBorder =
RRect.fromRectAndRadius(Offset.zero & size, const Radius.circular(12));
final rrectShadow =
RRect.fromRectAndRadius(const Offset(0, 2) & size, const Radius.circular(12));
final shadowPaint = Paint()
..color = Colors.lightGreen
..style = PaintingStyle.stroke
..strokeWidth = 3
..maskFilter = MaskFilter.blur(BlurStyle.solid, 20);
canvas.drawRRect(rrectShadow, shadowPaint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
I want to build a reusable card widget, it will have an image and text with some custom design layout. I tried everything I could, but wasn't able to achieve the desired result. Any help would be much appreciated.
This is what I want to do
I'm stuck here
This is my code
class ReusabelCard extends StatelessWidget {
ReusabelCard(
{this.cardChild, #required this.assetImagePath, #required this.cardText});
final Widget cardChild;
final String assetImagePath;
final String cardText;
#override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.35,
width: MediaQuery.of(context).size.width * 0.5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(MediaQuery.of(context).size.width * 0.5 * 0.28),
),
child: Stack(
children: [
LayoutBuilder(
builder: (context, contraint) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(
Icons.trip_origin,
size: contraint.biggest.width,
color: Colors.grey[300],
),
Container(
height: MediaQuery.of(context).size.height*0.05,
width: MediaQuery.of(context).size.width,
color: Colors.green,
),
],
);
},
),
],
)
);
}
}
Use ClipRRect to do it:
ClipRRect(
borderRadius: BorderRadius.circular(50.0), //clipping the whole widget
child: Container(
height: MediaQuery.of(context).size.height * 0.4, //I adjusted here for responsiveness problems on my device
width: MediaQuery.of(context).size.width * 0.5,
color: Colors.white,
child: LayoutBuilder(
builder: (context, constraint) {
return Stack(
children: [
Center(
child: Icon(
Icons.trip_origin,
size: constraint.biggest.width,
color: Colors.grey[300],
),
),
Positioned(
right: 0,
left: 0,
top: 20.0,
child: Icon(
Icons.sports_volleyball_rounded, //just to represent the ball
size: constraint.biggest.width * 0.5,
),
),
Positioned(
bottom: 0.0,
child: Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height * 0.1,
width: constraint.biggest.width,
color: Colors.yellow[700],
child: Text(
'Sports',
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Colors.white),
),
),
),
],
);
},
),
),
);