How to keep my Curved Navigation Bar visible when navigating to another page? - flutter

I'm making this music app and when I click my image of the 3D Perspective PageView, the new page shows up well but the Curved Navigation Bar isn't showing up. I tired to find every resources on the internet but they are all saying about how to redirect with clicking the bottom nav bar.
This is my main.dart file
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/bottomnavbar.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
//title: 'Twitch Player Example',
//title: 'Perspective PageView',
theme: ThemeData(
useMaterial3: true,
),
home: const BottomNavBar(),
);
}
}
And this is my home.dart file.
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
import 'package:secondlife_mobile/screens/artist_1.dart';
import 'package:secondlife_mobile/screens/artist_2.dart';
import 'package:secondlife_mobile/screens/artist_3.dart';
import 'package:secondlife_mobile/screens/artist_4.dart';
import 'package:url_launcher/url_launcher.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
Future<void> _launchURL(String url) async {
final Uri uri = Uri(scheme: "https", host: url);
if (!await launchUrl(
uri,
mode: LaunchMode.inAppWebView,
)) {
throw 'Can not launch url';
}
}
#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;
int currentIndex = 0;
final PageController controller = PageController();
List<String> images = [
"https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q",
"https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw",
"https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ",
"https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w",
"https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg",
"https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA",
"https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g",
"https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug",
"https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg",
"https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ",
];
#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(
mainAxisSize: MainAxisSize.min,
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: 15),
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) {
if (index == 0) {
return InkWell(
//you should use InkWell for onTap or thing like that!!!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const FirstArtist(),
),
);
},
child: MyPage(
number: index.toDouble(),
fraction: fraction,
),
);
}
if (index == 1) {
return InkWell(
//you should use InkWell for onTap or thing like that!!!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const SecondArtist(),
),
);
},
child: MyPage(
number: index.toDouble(),
fraction: fraction,
),
);
}
if (index == 2) {
return InkWell(
//you should use InkWell for onTap or thing like that!!!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ThirdArtist(),
),
);
},
child: MyPage(
number: index.toDouble(),
fraction: fraction,
),
);
}
if (index == 3) {
return InkWell(
//you should use InkWell for onTap or thing like that!!!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const FourthArtist(),
),
);
},
child: MyPage(
number: index.toDouble(),
fraction: fraction,
),
);
} else {
return const Text("Can't find anything");
}
},
),
),
),
),
),
Transform.translate(
offset: const Offset(0, -85),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Watch videos',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
//https://www.youtube.com/watch?v=7a_RXHOkJLM
//https://github.com/Programmer9211/Flutter-Carousel-Slider/blob/main/lib/main.dart
Transform.translate(
offset: const Offset(0, -65),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: SizedBox(
height: 162,
width: 335,
child: PageView.builder(
controller: controller,
onPageChanged: (index) {
setState(() {
currentIndex = index % images.length;
});
},
itemBuilder: (context, index) {
return InkWell(
//you should use InkWell for onTap or thing like that!!!
onTap: () {
print("Tapped watch Videos Imageeeee");
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 35),
child: SizedBox(
height: 100,
width: 400,
child: Image.network(
images[index % images.length],
fit: BoxFit.fill,
),
),
),
);
},
),
),
),
],
),
),
////Your Playlist of the week text
Transform.translate(
offset: const Offset(0, -30),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
Transform.translate(
offset: const Offset(0, -15),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album1.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album2.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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),
),
),
),
],
);
}
}

There is a package called persistent_bottom_nav_bar 5.0.2.
Step1: Create a new StatefulWidget called PersistentNavBar that contains the CurvedNavigationBar widget:
Step2: Wrap your entire app with a PageView and set its children to the pages you want to navigate to. For each page, you can set its bottomNavigationBar to the PersistentNavBar widget.

Related

How to make my 3D Perspective PageView to navigate to specific page when I click?

I'm trying to make my 3D Perspective PageView to navigate to specific page when I click the center Image. I followed this tutorial on youtube (https://www.youtube.com/watch?v=o-98lLOxohw) and customized it on my own project.
This is how my project looks like right now when I run it.
And this is my home.dart file.
I'll include my github repository link if you want to have a better look.
https://github.com/loupdaniel/Second-Life_Mobile
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.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
Future<void> _launchURL(String url) async {
final Uri uri = Uri(scheme: "https", host: url);
if (!await launchUrl(
uri,
mode: LaunchMode.inAppWebView,
)) {
throw 'Can not launch url';
}
}
#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;
int currentIndex = 0;
final PageController controller = PageController();
List<String> images = [
"https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q",
"https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw",
"https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ",
"https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w",
"https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg",
"https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA",
"https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g",
"https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug",
"https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg",
"https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ",
];
#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(
mainAxisSize: MainAxisSize.min,
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: 15),
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,
);
},
),
),
),
),
),
Transform.translate(
offset: const Offset(0, -85),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Watch videos',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
//https://www.youtube.com/watch?v=7a_RXHOkJLM
//https://github.com/Programmer9211/Flutter-Carousel-Slider/blob/main/lib/main.dart
Transform.translate(
offset: const Offset(0, -65),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: SizedBox(
height: 162,
width: 335,
child: PageView.builder(
controller: controller,
onPageChanged: (index) {
setState(() {
currentIndex = index % images.length;
});
},
itemBuilder: (context, index) {
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 35),
child: SizedBox(
height: 100,
width: 400,
child: Image.network(
images[index % images.length],
fit: BoxFit.fill,
),
),
);
},
),
),
),
],
),
),
////Your Playlist of the week text
Transform.translate(
offset: const Offset(0, -30),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
Transform.translate(
offset: const Offset(0, -15),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album1.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album2.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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),
),
),
),
],
);
}
}
You can use GestureDetector or InkWell Widget to handle onTap or touch function on any Widget. Add either of this Widget in your code
Sample Code : -
GestureDetector(
onTap: (() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SecondPage()), // Navigate to SecondPage
);
}),
child: 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,
);
},
),
),
),
),
),
),
Full Code : -
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.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
Future<void> _launchURL(String url) async {
final Uri uri = Uri(scheme: "https", host: url);
if (!await launchUrl(
uri,
mode: LaunchMode.inAppWebView,
)) {
throw 'Can not launch url';
}
}
#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;
int currentIndex = 0;
final PageController controller = PageController();
List<String> images = [
"https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q",
"https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw",
"https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ",
"https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w",
"https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg",
"https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA",
"https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g",
"https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug",
"https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg",
"https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ",
];
#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(
mainAxisSize: MainAxisSize.min,
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: 15),
GestureDetector(
onTap: (() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const SecondPage()), // Navigate to SecondPage
);
}),
child: 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,
);
},
),
),
),
),
),
),
Transform.translate(
offset: const Offset(0, -85),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Watch videos',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
//https://www.youtube.com/watch?v=7a_RXHOkJLM
//https://github.com/Programmer9211/Flutter-Carousel-Slider/blob/main/lib/main.dart
Transform.translate(
offset: const Offset(0, -65),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: SizedBox(
height: 162,
width: 335,
child: PageView.builder(
controller: controller,
onPageChanged: (index) {
setState(() {
currentIndex = index % images.length;
});
},
itemBuilder: (context, index) {
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 35),
child: SizedBox(
height: 100,
width: 400,
child: Image.network(
images[index % images.length],
fit: BoxFit.fill,
),
),
);
},
),
),
),
],
),
),
////Your Playlist of the week text
Transform.translate(
offset: const Offset(0, -30),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
Transform.translate(
offset: const Offset(0, -15),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album1.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
'assets/images/album2.jpg',
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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,
),
GestureDetector(
onTap: () {
_launchURL("www.google.com");
},
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),
),
),
),
],
);
}
}

How to modify the position of the text and the listview?

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.

large image when clicking - flutter

I have an algorithm working, and I need to click on the image to show it on the entire screen, I have not succeeded, I send all the code, add a comment "// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK" which is the image that I want to make it look large when I click it, I have tried in several ways but I have not been able to solve it, and the only thing I am missing is this functionality.
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tienda/models/productos_model.dart';
import 'package:tienda/pages/otra_pagina.dart';
import 'package:tienda/pages/crear_productos.dart';
import 'package:tienda/pages/pedido_lista.dart';
import 'package:tienda/services/firebase_services.dart';
import 'package:tienda/widgets/header.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
//title: 'Flutter Demo',
theme: ThemeData(
//primarySwatch: Colors.yellow,
primaryColor: Colors.yellow[800],
),
home: MyHomePage(title: 'RETO SAN JOSE CHAPARRAL'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<ProductosModel> _productosModel = List<ProductosModel>();
List<ProductosModel> _listaCarro = [];
FirebaseService db = new FirebaseService();
StreamSubscription<QuerySnapshot> productSub;
#override
void initState() {
super.initState();
_productosModel = new List();
productSub?.cancel();
productSub = db.getProductList().listen((QuerySnapshot snapshot) {
final List<ProductosModel> products = snapshot.documents
.map((documentSnapshot) =>
ProductosModel.fromMap(documentSnapshot.data))
.toList();
setState(() {
this._productosModel = products;
});
});
}
#override
void dispose() {
productSub?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0, top: 8.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 38,
),
if (_listaCarro.length > 0)
Padding(
padding: const EdgeInsets.only(left: 2.0),
child: CircleAvatar(
radius: 8.0,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
child: Text(
_listaCarro.length.toString(),
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 12.0),
),
),
),
],
),
onTap: () {
if (_listaCarro.isNotEmpty)
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Cart(_listaCarro),
),
);
},
),
)
],
),
drawer: Container(
width: 170.0,
child: Drawer(
child: Container(
width: MediaQuery.of(context).size.width * 0.5,
//color: Colors.black, //color de menu principal
color: Colors.yellow[800],
child: new ListView(
padding: EdgeInsets.only(top: 30.0),
children: <Widget>[
Container(
height: 120,
child: new UserAccountsDrawerHeader(
accountName: new Text(''),
accountEmail: new Text(''),
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.fill,
image: AssetImage('assets/images/food1x.png'),
),
),
),
),
new Divider(),
new ListTile(
title: new Text(
'productos',
style: TextStyle(color: Colors.white),
),
trailing: new Icon(
Icons.fastfood,
size: 30.0,
color: Colors.white,
),
onTap: () =>
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => CrearProductos(),
)),
),
new Divider(),
],
),
),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
WaveClip(),
Container(
color: Colors.transparent,
padding: const EdgeInsets.only(left: 24, top: 48),
height: 170,
child: ListView.builder(
itemCount: _productosModel.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
height: 300,
padding: new EdgeInsets.only(
left: 10.0, bottom: 10.0),
child: Card(
elevation: 7.0,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(24)),
child: AspectRatio(
aspectRatio: 1,
child: CachedNetworkImage(
imageUrl:
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child:
CupertinoActivityIndicator(
radius: 15,
));
}),
),
),
),
],
);
},
))
],
),
Container(height: 3.0, color: Colors.grey),
SizedBox(
height: 5.0,
),
Container(
color: Colors.grey[300],
height: MediaQuery.of(context).size.height / 1.5,
child: GridView.builder(
padding: const EdgeInsets.all(4.0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: _productosModel.length,
itemBuilder: (context, index) {
final String imagen = _productosModel[index].image;
var item = _productosModel[index];
return Card(
elevation: 4.0,
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: CachedNetworkImage(
// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK
imageUrl:
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child:
CupertinoActivityIndicator(
radius: 15,
));
}),
),
Text(
'${_productosModel[index].name}',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20.0),
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
height: 25,
),
Text(
'${_productosModel[index].price.toString()}COP',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
color: Colors.black),
),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
child: (!_listaCarro
.contains(item))
? Icon(
Icons.shopping_cart,
color: Colors.yellow[800],
size: 38,
)
: Icon(
Icons.shopping_cart,
color: Colors.red,
size: 38,
),
onTap: () {
setState(() {
if (!_listaCarro
.contains(item))
_listaCarro.add(item);
else
_listaCarro.remove(item);
});
},
),
),
),
],
)
],
),
],
));
},
)),
],
),
)),
));
}
}
Another solution is to show the larger image on the same screen using the dialog below.
InkWell(
onTap: () => showDialog(
builder: (BuildContext context) => AlertDialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(2),
title: Container(
decoration: BoxDecoration(),
width: MediaQuery.of(context).size.width,
child: Expanded(
child: Image.network(
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.fitWidth,
),
),
),
),
context: context),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
BaseUrl.host + posts!.imageUrl!,
fit: BoxFit.cover,
),
),
)
You can create a new page, wrap the image widget in a InkWell widget, and when tapped navigate to the new page showing the image.
EDIT:
Your widget image would become:
// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK
return InkWell(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => ImageScreen(
url: '${_productosModel[index].image}' + '?alt=media',
),
),
),
child: Expanded(
child: CachedNetworkImage(
imageUrl: '${_productosModel[index].image}' + '?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child: CupertinoActivityIndicator(
radius: 15,
),
);
},
),
),
),
And then you create a new stateless widget which it builds a:
import 'package:flutter/material.dart';
class ImageScreen extends StatelessWidget {
final String? url;
ImageScreen({
Key? key,
#required this.url,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Expanded(
child: CachedNetworkImage(
imageUrl: '${this.url}',
// Ajust the image changing the box fit attributte
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child: CupertinoActivityIndicator(
radius: 15,
),
);
},
),
),
);
}
}
After that when you click the app navigates to a new screen rendering only the image. You can add a back button later.

How to make infinity scroll layout in flutter? (Updated)

I'm trying to make listview using data from REST API, the position is below my image , but the layout reach its limit, so i can't create it , and showing this error
here my code, (Updated Code)
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:schoolofparentingalfa/assets/color/color.dart';
class Home extends StatefulWidget {
#override
Home2 createState() => Home2();
}
class Home2 extends State<Home> {
var colorsop = new Colorsop();
var apiconfig = new ApiConfig();
var apiClient = new ApiClient();
#override
void initState() {
super.initState();
}
//To call list from api
Future<List<Artikel>> getNews() async {
// future is used to handle the error when calling api > Future + async or await
var data = await http.get(
'https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=c4349a84570648eaa7be3cd673cc262b');
var jsonData = json.decode(data.body);
var newsData =
jsonData['articles']; //to retrieve data from articles array of api
List<Artikel> news = []; // create array
for (var data in newsData) {
//assign data into News model array list from articles array of api
Artikel newsItem = Artikel(
data['title'], data['description'], data['urlToImage']);
news.add(newsItem);
}
return news;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: <Widget>[
Positioned(
top: 0,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.yellow[800],
child: Align(
alignment: Alignment.center,
child: Text("Halo, Selamat Datang", style: TextStyle(color: Colors.white, fontSize: 25),))),
),
Positioned(
top: 90,
bottom: 0,
right: 0,
left: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: 600,
decoration: BoxDecoration(
color: Colors.white,
),
child: GridView.count(
crossAxisCount: 1,
children: [
Container( // Container 1
child: Row(
children: <Widget>[
Image.asset(
'lib/assets/image/kelas_online.png',
height: 120,
width: 150,
),
Image.asset(
'lib/assets/image/tanyaahli.png',
height: 120,
width: 150,
),
],
),
),
Container( // Container 2
child: Row(
children: <Widget>[
Image.asset(
'lib/assets/image/workshop_online.png',
height: 120,
width: 150,
),
Image.asset(
'lib/assets/image/MitraSekolah.png',
height: 120,
width: 150,
),
],
),
),
Container( //Container 3
margin: EdgeInsets.only(top: 15, bottom: 30, left: 20),
padding: EdgeInsets.symmetric(horizontal: 15),
child: FutureBuilder(
future: getNews(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
//snapshot is same with response
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
// to retrieve data as all array indexes
itemBuilder: (BuildContext context, int index) {
// is same with holder
return InkWell(
// Inkwell is used to apply card view
onTap: () {
Artikel news = new Artikel(snapshot.data[index].post_link, snapshot.data[index].description, snapshot.data[index].post_image);//is used to onclick
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new Details(news: news)
));
},
child: Card(
child: Row(
children: <Widget>[
Container(
width: 120.0,
height: 110.0,
child: ClipRRect(
//for corner radius
borderRadius:
BorderRadius.all(Radius.circular(8)),
//to retrieve image from array
child: snapshot.data[index].post_image == null
? Image.network(
'https://cdn2.vectorstock.com/i/1000x1000/70/71/loading-icon-load-icon-wait-for-a-wait-please-wait-vector-24247071.jpg')
: Image.network(
snapshot.data[index].post_image,
width: 100,
fit: BoxFit.fill,
),
),
),
Expanded(
child: ListTile(
//include title and subtitle
title: Text(snapshot.data[index].post_title),
subtitle: Text(snapshot.data[index].post_link == null
? 'Unknown Author'
: snapshot.data[index].post_link),
),
)
],
),
),
);
},
);
}
},
),
),
],
),
)
)
],),
);
}
}
}
class Details extends StatelessWidget{
final Artikel news;
Details({this.news}); // create constructor
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Column(
children: <Widget>[
Stack( //little same with expanded
children: <Widget>[
Container(
height: 400,
child: Image.network('${this.news.post_image}',
fit: BoxFit.fill,),
),
AppBar(
backgroundColor: Colors.transparent,
leading: InkWell(
child: Icon(Icons.arrow_back_ios),
onTap: () => Navigator.pop(context),
),
elevation: 0,
)
],
),
Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: <Widget>[
SizedBox( // for title
height: 10,
),
Text(
'${this.news.post_title}',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 20,
letterSpacing: 0.2,
wordSpacing: 0.6
),
),
SizedBox( // for description
height: 20,
),
Text(
this.news.post_link,
style: TextStyle(
color: Colors.black54,
fontSize: 16,
letterSpacing: 0.2,
wordSpacing: 0.3
),
)
],
),
)
],
),
),
),
);
}
}
class Artikel {
final String post_title;
final String post_link;
final String post_image;
//Alt+insert > constructor
Artikel(this.post_title, this.post_link, this.post_image);
}
Can anyone help me?
Updated Screenshot .............................................................................
you can replace the code and check
return Scaffold(
body: Stack(children: <Widget>[
Positioned(
top: 0,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.yellow[800],
child: Align(
alignment: Alignment.center,
child: Text("Halo, Selamat Datang", style: TextStyle(color: Colors.white, fontSize: 25),))),
),
Positioned(
top: 90,
bottom: 0,
right: 0,
left: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: 600,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topLeft:Radius.circular(20), topRight:Radius.circular(20)) ),
child:
GridView.count(
crossAxisCount: 2,
children: List.generate(5, (index) {
return Padding(
padding: const EdgeInsets.all(24.0),
child: GridTile(child: Image.network("https://upload.wikimedia.org/wikipedia/commons/6/6d/Good_Food_Display_-_NCI_Visuals_Online.jpg"),),
);
}) ,),)
)
],),
);

How to create multiple horizontal `GridView` in the same screen using flutter

Is there's a way to create a lists of GridViews as the below image in one screen...
I have a some Screen as the below one:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
var _showOnlyFavorites = false;
AnimationController animationController;
bool multiple = true;
#override
void initState() {
animationController = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
super.initState();
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 0));
return true;
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.white,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder:
(BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return PropertiesGrid(_showOnlyFavorites);
}
},
),
),
],
),
);
}
},
),
);
}
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child:
Image.asset('assets/images/logo.png', fit: BoxFit.contain),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Icon(
multiple ? Icons.dashboard : Icons.view_agenda,
color: AppTheme.dark_grey,
),
onTap: () {
setState(() {
multiple = !multiple;
});
},
),
),
),
),
],
),
);
}
}
as I have a widget which have the GridView.builder as the below code:
import 'package:aradi_online_vtwo/providers/properties.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/properties.dart';
import './property_item.dart';
class PropertiesGrid extends StatelessWidget {
final bool showFavs;
PropertiesGrid(this.showFavs);
#override
Widget build(BuildContext context) {
final productsData = Provider.of<Properties>(context);
final products = showFavs ? productsData.favoriteItems : productsData.items;
return GridView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: products.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
// builder: (c) => products[i],
value: products[i],
child: PropertyItem(
// products[i].id,
// products[i].title,
// products[i].imageUrl,
),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
), scrollDirection: Axis.horizontal,
);
}
}
I tried to set the height of the grid by wrapping it with a Container and set the height of it as to add more grids but it doesn't work.
and here's my Grid Item widget code:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/property.dart';
class PropertyItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
final property = Provider.of<Property>(context, listen: false);
return InkWell(
onTap: () => {},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
elevation: 7,
margin: EdgeInsets.all(2),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
// color: Colors.transparent,
child: Image.asset(
property.image,
fit: BoxFit.fill,
),
),
Positioned(
top: 8,
right: 8,
child: Consumer<Property>(
builder: (ctx, property, _) => IconButton(
icon: Icon(
property.isFavorite ? Icons.favorite : Icons.favorite_border,
),
color: Colors.red,
onPressed: () {
property.toggleFavoriteStatus();
},
),
),
),
Positioned(
right: 20,
top: 100,
child: Container(
width: 300,
color: Colors.black54,
padding: EdgeInsets.symmetric(
vertical: 5,
horizontal: 20,
),
child: Text(
property.title,
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
softWrap: true,
overflow: TextOverflow.fade,
),
),
)
],
),
),
);
}
}
You'll need a column where each ListView or GridView is wrapped inside a SizedBox (if you have a specific height) and you also can use Expanded to take whatever available space (like the last one in the given example):
You can post the code below in dartpad.dev and see how it works:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Second List"),
alignment: Alignment.centerRight,
),
),
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Third List"),
alignment: Alignment.centerRight,
),
),
Expanded(
//height: 200,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
scrollDirection: Axis.vertical,
itemCount: 20,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
],
),
);
}
}