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 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),
),
),
),
],
);
},
),
),
);
I want to achieve an effect similar to this one:
Here's what I have: (Blue container is hidden below the appBar)
And this is my current code:
Widget build(BuildContext context) {
return Scaffold(
appBar: GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
body: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The GradesAppBar is a Container with boxShadow, borderRadius and gradient decoration.
When you're using stack to achieve this UI approach you should remove the AppBar and make it like this :-
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The most important thing; if your GradesAppBar extends PreferredSizeWidget I think you should replace it with Container and give it some cool decorations as you want :")
I want to open new page when I swipe the circle in the middle of the screen. that is when I swipe blue circle left a new page should open and when I swipe right another new page should open.
Similarly when I swipe pink circle bottom another new page should open
Here is my code:
import 'package:flutter/material.dart';
class FirstRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: 300.0,
width: 150.0,
child: Stack(
children: <Widget>[
Positioned(
top: 25,
child: Container(
height: 150.0,
width: 150.0,
decoration: BoxDecoration(
shape:BoxShape.circle,
color:Colors.lightBlue,
),
),
),
Positioned(
bottom: 25,
child: Opacity(
opacity: 0.45,
child: Container(
height: 150.0,
width: 150.0,
decoration: BoxDecoration(
shape:BoxShape.circle,
color:Colors.pinkAccent,
),
),
),
),
],
),
),
),
);
}
}
wrap Positioned() with SwipeDetector() Widget
Have a look at this example
SwipeDetector(
onSwipeRight: () {
//push new page
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new YourNewPage()));
},
child: //Your circle here
Positioned(
top: 25,
child: Container(
height: 150.0,
width: 150.0,
decoration: BoxDecoration(
shape:BoxShape.circle,
color:Colors.lightBlue,
),
),
),
)
I need to put icon into CircleAvatar Widget to allow user upload his image.
Something like this:
This is my code:
child: CircleAvatar(
child: Stack(
children: <Widget>[
Positioned(
bottom: 0,
right: 0,
left: 0,
height: 33,
child: Container(
height: 20,
width: 30,
color: Color.fromRGBO(0, 0, 0, .74),
child: Center(
child:
Icon(Icons.photo_camera, color: Colors.grey),
),
),
)
],
),
radius: 68.0,
backgroundImage:
NetworkImage('https://via.placeholder.com/300'),
backgroundColor: Colors.transparent,
)
But I have this result:
Internal box with camera icon overflow from parent widget (CircleAvatar);
What you want can be simply done with - ClipOval
Your Code:
body: Center(
child: CircleAvatar(
child: ClipOval(
child: Stack(
children: <Widget>[
Image.network('https://via.placeholder.com/300'),
Positioned(
bottom: 0,
right: 0,
left: 0,
height: 33,
child: GestureDetector(
onTap: (){
print('upload Clicked');
},
child: Container(
height: 20,
width: 30,
color: Color.fromRGBO(0, 0, 0, .74),
child: Center(
child: Icon(Icons.photo_camera, color: Colors.grey),
),
),
),
),
],
),
),
radius: 68.0,
// backgroundImage: NetworkImage('https://via.placeholder.com/300'),
backgroundColor: Colors.transparent,
),
),
Output:
You can create your Custom Clipper to give the circular bottom to your widget.
You need to use the ClipPath widget for it, pass your widget in your case Container containing your camera icon.
and in clipper pass your CustomClipper.
ClipPath
return ClipPath(
child: your_widget,
clipper: BottomWaveClipper(),
);
CustomCliper
class BottomCircleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
//your path to draw circle
}
#override
bool shouldReclip(TriangleClipper oldClipper) => false;
}
Here are some links that will help you.
https://iirokrankka.com/2017/09/04/clipping-widgets-with-bezier-curves-in-flutter/
https://medium.com/flutter-community/clipping-in-flutter-e9eaa6b1721a