How to blur the upcoming and previous widget in PageView builder - Flutter - android

I'm trying to achieve this:
For now, I have created a weather Widget and added a PageView builder. I want to fade the upcoming and previous widgets in PageView and the current Widget to be more clear. For testing purposes I added blur to the widget which are not in focus.
Problem::
I'm not able to figure out how I can blur the upcoming widget. The
current and the previous widgets are blured when I swap through them.
Here is my code currently:
page_view_gallary.dart
class PageviewGallery extends StatefulWidget {
#override
_PageviewGalleryState createState() => _PageviewGalleryState();
}
class _PageviewGalleryState extends State<PageviewGallery> {
var listWidgets = [
WeatherCard(
isActive: false,
location: "Los Angeles, CA, USA",
temperature: 15,
localTimeEpoch: 1675101764,
weatherState1: "Strong Winds",
weatherState2: "Cloudy"),
WeatherCard(
isActive: true,
location: "San Andreas, CA, USA",
temperature: 15,
localTimeEpoch: 1675101764,
weatherState1: "Strong Winds",
weatherState2: "Cloudy"),
WeatherCard(
isActive: true,
location: "Los Angeles, CA, USA",
temperature: 15,
localTimeEpoch: 1675101764,
weatherState1: "Strong Winds",
weatherState2: "Cloudy"),
WeatherCard(
isActive: false,
location: "Los Angeles, CA, USA",
temperature: 15,
localTimeEpoch: 1675101764,
weatherState1: "Strong Winds",
weatherState2: "Cloudy"),
WeatherCard(
isActive: false,
location: "Los Angeles, CA, USA",
temperature: 15,
localTimeEpoch: 1675101764,
weatherState1: "Strong Winds",
weatherState2: "Cloudy"),
];
final PageController ctrl = PageController(
viewportFraction: 0.5,
);
int currentPage = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ExpandablePageView.builder(
controller: ctrl,
itemCount: listWidgets.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, int index) {
// Active page
bool active = index == currentPage;
return _buildStoryPage(active, index);
}),
));
}
#override
void initState() {
super.initState();
ctrl.addListener(() {
int pos = ctrl.page!.round();
if (currentPage != pos) {
{
setState(() {
currentPage = pos;
});
}
}
});
}
#override
void dispose() {
ctrl.dispose();
super.dispose();
}
_buildStoryPage(bool active, int index) {
// Animated Properties
final double blur = active ? 30 : 0;
final double offset = active ? 20 : 0;
final double top = active ? 100 : 200;
final double bottom = active ? 100 : 200;
WeatherCard cWidget = listWidgets[index];
// print("$index, $currentPage");
return BackdropFilter(
filter: ImageFilter.blur(
sigmaX: active ? 2.0 : 0.0, sigmaY: active ? 2.0 : 0.0),
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
curve: Curves.easeOutQuint,
margin: EdgeInsets.only(top: top, bottom: 100, right: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red,
boxShadow: [
BoxShadow(
color: Colors.black87,
blurRadius: blur,
offset: Offset(offset, offset))
]),
child: cWidget,
),
);
}
}
weather_card.dart
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class WeatherCard extends StatelessWidget {
final String location;
final int temperature;
final int localTimeEpoch;
final String weatherState1;
final String weatherState2;
bool isActive;
WeatherCard(
{super.key,
required this.location,
required this.temperature,
required this.localTimeEpoch,
required this.weatherState1,
required this.weatherState2,
required this.isActive});
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: 450,
width: 250,
decoration: const BoxDecoration(color: Colors.transparent),
),
Positioned(
top: 100,
left: 10,
right: 10,
bottom: 100,
child: Container(
height: 250,
width: 250,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: const Color.fromARGB(255, 44, 44, 44).withOpacity(0.5),
spreadRadius: 2,
blurStyle: BlurStyle.normal,
blurRadius: 7,
offset: const Offset(0, 3), // changes position of shadow
),
], color: Colors.white, borderRadius: BorderRadius.circular(50)),
child: Padding(
padding: const EdgeInsets.only(top: 100.0, left: 20, right: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
location,
style: GoogleFonts.alegreyaSans(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black),
),
Row(
children: [
Text(
"$temperature",
style: GoogleFonts.alegreyaSans(
fontWeight: FontWeight.bold,
fontSize: 64,
color: Colors.black),
),
Text(
"°C",
style: GoogleFonts.alegreyaSans(
fontWeight: FontWeight.w500,
fontSize: 14,
color: Colors.black),
),
],
),
Text(
"Sunday, 11 am",
style: GoogleFonts.alegreyaSans(
fontWeight: FontWeight.w500,
fontSize: 14,
color: Colors.black.withOpacity(0.5)),
),
],
),
),
),
),
Positioned(
top: -100,
left: 0,
right: 0,
bottom: 0,
child: Image.asset("assets/images/shaddow.png")),
Positioned(
top: -300,
left: 0,
right: 0,
bottom: 0,
child: Image.asset("assets/images/moon_cloud.png")),
Positioned(
top: 330,
left: 50,
right: 50,
bottom: 60,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: const Color(0xff5E4FC1),
),
width: 20,
// color: Colors.blue,
child: Center(
child: Text(
"VIEW STATS",
style: GoogleFonts.alegreyaSans(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14),
)),
)),
],
);
}
}
Current Output

To blur the upcoming and previous widgets in a PageView in Flutter, you can use a Stack widget with a BackdropFilter and wrap each child of the PageView with the Stack.
Here's an example:
Stack(
children: [
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.transparent,
),
),
YourWidgetHere(),
],
)
Apply this to each child of the PageView builder, for example:
PageView.builder(
itemBuilder: (context, index) {
return Stack(
children: [
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.transparent,
),
),
YourWidgetHere(),
],
);
},
)

Related

The parameter 'size' can't have a value of 'null' because of its type in Dart

I am new to flutter and dart , I have a problem where the parameter size cant have null value. I tried to search in the google the same problem that people had been facing and the solution is to add 'required'. i had tried that but the problem is in my body
Below here is my CustomCard().
import 'package:flutter/material.dart';
import '../../constants.dart';
class CustomCard extends StatefulWidget {
final Size size;
final Icon icon;
final String title, statusOn, statusOff;
const CustomCard(
{ required Key key,
required this.size,
required this.icon,
required this.title,
required this.statusOn,
required this.statusOff})
: super(key: key);
#override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Alignment> _animation;
bool isChecked = true;
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 350),
);
_animation = Tween<Alignment>(
begin: Alignment.bottomCenter, end: Alignment.topCenter)
.animate(
CurvedAnimation(
parent: _animationController,
curve: Curves.linear,
reverseCurve: Curves.easeInBack,
),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
height: 140,
width: widget.size.width * 0.35,
decoration: BoxDecoration(
color: kBgColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 8,
offset: Offset(3, 3),
),
BoxShadow(
color: Colors.white,
blurRadius: 8,
offset: Offset(-3, -3),
),
],
),
child: Padding(
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
widget.icon,
AnimatedBuilder(
animation: _animationController,
builder: (animation, child) {
return GestureDetector(
onTap: () {
setState(() {
if (_animationController.isCompleted) {
_animationController.animateTo(20);
} else {
_animationController.animateTo(0);
}
isChecked = !isChecked;
});
},
child: Container(
height: 40,
width: 25,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey.shade50,
boxShadow: [
BoxShadow(
color: Colors.grey.shade200,
blurRadius: 0,
offset: Offset(3, 3),
),
BoxShadow(
color: Colors.black12,
blurRadius: 5,
offset: Offset(-3, -3),
),
],
),
child: Align(
alignment: _animation.value,
child: Container(
height: 15,
width: 15,
margin: EdgeInsets.symmetric(
vertical: 2, horizontal: 1),
decoration: BoxDecoration(
color: isChecked
? Colors.grey.shade300
: kGreenColor,
shape: BoxShape.circle,
),
),
),
),
);
},
),
],
),
SizedBox(height: 10),
Text(
widget.title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: kBlueColor,
),
),
Text(
isChecked ? widget.statusOff : widget.statusOn,
style: TextStyle(
fontWeight: FontWeight.bold,
color: kGreenColor,
),
),
],
)),
);
}
}
And below here is my Body.dart
import 'package:flutter/material.dart';
import 'package:neew/constants.dart';
import 'package:neew/MainScreen/custom_card.dart';
class MainScreenBody extends StatefulWidget {
#override
_MainScreenBodyState createState() => _MainScreenBodyState();
}
class _MainScreenBodyState extends State<MainScreenBody> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
SizedBox(height: size.height * 0.1),
Center(
child: Text(
"My Home",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 25,
),
),
),
SizedBox(height: size.height * 0.05),
CustomCard(
size: size,
icon: Icon(
Icons.home_outlined,
size: 55,
color: Colors.grey.shade400,
),
title: 'Entry',
statusOn: 'OPEN',
statusOff: 'LOCKED',
)
],
),
);
}
}
The error that i detect in body dart is in CustomCard().
Please help me, I will really appreciate it.

How fix scaling for small screen size in flutter? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Target: respect variant screens size.
Problem: Screen's UI does not display well on different devices and producing UI's error
For example: on the iPhone 13 emulator, everything looks as it should, but when you use a smartphone with a screen resolution of 1280x768, everything breaks down
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'auth.dart';
void main() {
runApp(const Auth());
}
class Main extends StatelessWidget {
const Main({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MainPage(),
);
}
}
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight: 0,
),
backgroundColor: const Color.fromARGB(255, 247, 255, 247),
body: SafeArea(
bottom: false,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage('assets/images/spikelets.png'),
fit: BoxFit.fitWidth,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Stack(
children: [
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(top: 35, left: 49),
child: Text(
'Добро',
style: TextStyle(
fontFamily: 'GoodVibesCyr',
fontSize: 92,
color: Colors.green,
),
)),
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(top: 100, left: 35),
child: Text(
'пожаловать!',
style: TextStyle(
fontFamily: 'TTCommons',
fontSize: 54,
color: Colors.green,
fontWeight: FontWeight.bold,
),
)),
],
),
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(top: 20, left: 25),
child: Text(
'Мобильный заказ',
style: TextStyle(
fontFamily: 'TTCommons',
fontWeight: FontWeight.bold,
fontSize: 36,
color: Colors.black,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 150,
width: 150,
margin: EdgeInsets.only(top: 15),
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage(
'assets/images/backgroundMainButtons.png'),
fit: BoxFit.fitWidth,
),
boxShadow: [
BoxShadow(
color: Color.fromARGB(41, 0, 0, 0),
blurRadius: 6,
offset: Offset(0, 3), // changes position of shadow
),
],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
Container(
height: 150,
width: 150,
margin: EdgeInsets.only(left: 25, top: 15),
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage(
'assets/images/backgroundMainButtons.png'),
fit: BoxFit.fitWidth,
),
boxShadow: [
BoxShadow(
color: Color.fromARGB(41, 0, 0, 0),
blurRadius: 6,
offset: Offset(0, 3), // changes position of shadow
),
],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 150,
width: 150,
margin: EdgeInsets.only(top: 15),
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage(
'assets/images/backgroundMainButtons.png'),
fit: BoxFit.fitWidth,
),
boxShadow: [
BoxShadow(
color: Color.fromARGB(41, 0, 0, 0),
blurRadius: 6,
offset: Offset(0, 3), // changes position of shadow
),
],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
Container(
height: 150,
width: 150,
margin: EdgeInsets.only(left: 25, top: 15),
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage(
'assets/images/backgroundMainButtons.png'),
fit: BoxFit.fitWidth,
),
boxShadow: [
BoxShadow(
color: Color.fromARGB(41, 0, 0, 0),
blurRadius: 6,
offset: Offset(0, 3), // changes position of shadow
),
],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
],
),
Container(
margin: EdgeInsets.only(top: 15, right: 15),
width: 325,
height: 60,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Color.fromARGB(255, 67, 152, 71),
blurRadius: 0,
offset: Offset(0, 10), // changes position of shadow
),
],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: SizedBox(
width: 325,
height: 60,
child: ElevatedButton(
onPressed: () {},
child: Text(
'Товары недели',
style: TextStyle(
fontFamily: 'TTCommons',
fontSize: 32,
fontWeight: FontWeight.bold),
),
style: ElevatedButton.styleFrom(
alignment: Alignment.center,
shadowColor: Color.fromARGB(0, 0, 0, 0),
padding: EdgeInsets.all(15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20), // <-- Radius
),
),
),
),
),
],
),
),
),
);
}
}
The provided screen-shots declares more details:
Many possible solutions:
Wrap your Column widget by SingleChildScrollView
Replace Column with Scrollable Widget
Use "Wrap" Widget instead of "Column" Widget
SafeArea( /// controlls the reset of space
bottom: false,
child: Container( /// define the child height witch breaks the SafeArea physics
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: const BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage('assets/images/spikelets.png'),
fit: BoxFit.fitWidth,
),
),
child: Column( /// the child you gonna to update with above possabilities
--Update--
As you mentioned in comments about scaling your widgets, there are two ways as I know
first, you can use the flutter_screenutil
secondly, you can create your own sizing service like mine
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
class SizeConfig {
/// create singleton instance
SizeConfig._internal();
static final SizeConfig _instance = SizeConfig._internal();
factory SizeConfig() => _instance;
double screenWidth = Get.context.orientation == Orientation.portrait ? Get.mediaQuery.size.width : Get.mediaQuery.size.height;
double screenHeight = Get.context.orientation == Orientation.portrait ? Get.mediaQuery.size.height : Get.mediaQuery.size.width;
double infinityHeight() => double.infinity;
double infinityWidth() => double.infinity;
double blockSizeHorizontal() => screenWidth / 100;
double blockSizeVertical() => screenHeight / 100;
double _safeAreaHorizontal() => Get.mediaQuery.padding.left + Get.mediaQuery.padding.right;
double _safeAreaVertical() => Get.mediaQuery.padding.top + Get.mediaQuery.padding.bottom;
double safeBlockHorizontal() => (screenWidth - (Get.context.orientation == Orientation.portrait ? _safeAreaHorizontal() : _safeAreaVertical())) / 100;
double safeBlockVertical() => (screenHeight - (Get.context.orientation == Orientation.portrait ? _safeAreaVertical() : _safeAreaHorizontal())) / 100;
double fontSize50() => safeBlockHorizontal() * 5.0;
double fontSize51() => safeBlockHorizontal() * 5.1;
double fontSize52() => safeBlockHorizontal() * 5.2;
double fontSize53() => safeBlockHorizontal() * 5.3;
double fontSize54() => safeBlockHorizontal() * 5.4;
double fontSize55() => safeBlockHorizontal() * 5.5;
double fontSize56() => safeBlockHorizontal() * 5.6;
double fontSize57() => safeBlockHorizontal() * 5.7;
double fontSize58() => safeBlockHorizontal() * 5.8;
double fontSize59() => safeBlockHorizontal() * 5.9;
}
I use this SizeConfig() service with GetX, and using it as
width: SizeConfig().safeBlockHorizontal() * 10, // 10% from screen width
height: SizeConfig().safeBlockVertical() * 10 // 10% from screen height

Make an animated container behave like collapsing toolbar in flutter

Image looks like this
I have this widget that acts as a tab bar but was not create with a Tab bar. I want that widget to behave like a collapsing toolbar. Can anyone please help me out? This is the code
This is the code for the animated container which I want to behave like a collapsing toolbar...
Here is the code:
class Watching extends StatefulWidget {
final set_state;
const Watching(this.set_state, {Key? key}) : super(key: key);
#override
_WatchState createState() => _WatchState();
}
class _WatchState extends State<Watching> with TickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> animation, animation2;
final double startingHeight = 20.0;
List pages = [];
int index = 0;
GlobalKey _bottomNavigationKey = GlobalKey();
List titles = [feed, trending, explore];
#override
void initState() {
super.initState();
pages = [
MainPage(
set_state: widget.set_state,
),
TrendingPage(set_state: widget.set_state),
ExplorePage()
];
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 5));
animation = Tween<double>(begin: 125, end: 150).animate(_controller);
animation2 = Tween<double>(begin: 125, end: 150).animate(_controller);
_controller.forward(from: 0.0);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, twoFiftyDp),
child: Container(
color: Colors.teal,
child: Stack(
children: [
AnimatedContainer(
duration: Duration(milliseconds: 400),
width: animation.value,
height: animation.value <= 150 ? 150 : animation.value,
decoration: BoxDecoration(
color: Colors.teal,
),
),
Align(
alignment: Alignment.bottomRight,
child: RotationTransition(
turns: AlwaysStoppedAnimation(0 / 360),
child: ClipPath(
clipper: LeftRoundedClipper(flip: true),
child: AnimatedContainer(
duration: Duration(milliseconds: 400),
width: animation2.value - 10,
height: animation2.value *
MediaQuery.of(context)
.size
.height, //<= 150 ? 200 :animation.value,
decoration: BoxDecoration(
color: Colors.teal,
gradient: LinearGradient(
colors: [
Colors.lightGreen.withGreen(10),
Colors.greenAccent,
Colors.greenAccent
],
)),
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: CurvedNavigationBar(
key: _bottomNavigationKey,
height: 65,
color: Colors.white,
buttonBackgroundColor: Colors.transparent,
backgroundColor: Colors.transparent,
animationCurve: Curves.easeInOut,
animationDuration: Duration(milliseconds: 600),
index: 0,
onTap: (value) {
switch (value) {
case 0:
/* animation = Tween<double>(begin: 125, end: 0)
.animate(_controller);*/
animation2 = Tween<double>(begin: 125, end: 500)
.animate(_controller);
break;
case 1:
animation2 = Tween<double>(begin: 125, end: 700)
.animate(_controller);
/* animation = Tween<double>(begin: -10, end: 50)
.animate(_controller);*/
break;
case 2:
animation = Tween<double>(begin: 125, end: 500)
.animate(_controller);
animation2 = Tween<double>(begin: 150, end: 200)
.animate(_controller);
break;
}
setState(() {
index = value;
});
},
items: [
Text(
Main,
style: index == 0
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
Text(
trending,
style: index == 1
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
Text(
explore,
style: index == 2
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
],
),
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding:
const EdgeInsets.only(bottom: sixtyDp, left: tenDp),
child: ListTile(
title: Text(
titles[index],
style: TextStyle(
fontSize: fiftyDp,
fontWeight: FontWeight.bold,
color: Colors.white),
)),
)),
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(top: fiftyDp, left: twentyDp),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
index == 0
? ShowIcon(
iconName: 'assets/icons/User.png',
onIconTap: () {},
)
: SizedBox(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: fourteenDp),
child: ShowIcon(
iconName: 'assets/icons/MagnifyingGlass.png',
onIconTap: () {},
),
),
Padding(
padding: const EdgeInsets.only(right: fourteenDp),
child: ShowIcon(
iconName: 'assets/icons/BellRinging.png',
onIconTap: () {},
),
),
ShowIcon(
iconName: 'assets/icons/PaperPlane.png',
onIconTap: () {},
),
],
),
)
// Spacer(),
],
),
),
)
],
),
),
),
// body: pages[index],
body: DefaultTabController(
length: pages.length, child: NestedScrollView(headerSliverBuilder: (context, innerBoxIsScrolled) {
return <Widget>[
SliverList(delegate: SliverChildListDelegate([]))
];
}, body: pages[index]),
),
),
);
}
}

Is it possible to implement widgets using list in flutter?

I am creating a Journal mobile application which would work as a medium to view magazines and daily news updates. This is my first flutter project and I am totally new to flutter. So kindly excuse me if I had said something wrong about something or didnt provide enough information.
I used a code from github for the main page of my application and made few changes to accommodate my needs. Now in my code, the home page consists of a side menu bar and this bar consists of 4 buttons, namely Home, My Profile, Premium and FAQ. The GlobalKeys for the side menu bar is called using a list by the name _keys which is of the type GlobalKey. I tried changing the data type of the list _keys to Widget and then called the corresponding Widgets of the classes. But then two errors popped out.
The getter 'currentContext' isn't defined for the class 'Widget'.
The argument type 'Widget' can't be assigned to the parameter type 'GlobalKey<State>'.
Now I would like the list _keys to be of the type Widget in order for me to call upon it's corresponding widgets of Home, My Profile, Premium and FAQ from each of it's classes in order for me to view the corresponding pages. Or if it is not possible, I would love to know an alternative for it to start working.
Following is the code of my application.
import 'dart:math' as math;
import 'package:flutter/scheduler.dart';
import 'package:google_signin_example/google%20sign%20in/logged_in_widget.dart';
import 'package:google_signin_example/main app/lib/ui_3/TravelBean.dart';
import 'package:google_signin_example/main app/lib/ui_3/magazine/screens/home_screen.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/FAQ/faq.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_kiddos/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_news/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/premium/premium.dart';
import 'package:google_signin_example/widget/sign_up_widget.dart';
import 'detail_page.dart';
class HomePage1 extends StatefulWidget {
#override
_HomePage1State createState() => _HomePage1State();
}
class _HomePage1State extends State<HomePage1> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Container(
child: Row(
children: <Widget>[
LeftWidget(),
Expanded(
child: RightWidget(),
)
],
),
),
);
}
}
class LeftWidget extends StatefulWidget {
#override
_LeftWidgetState createState() => _LeftWidgetState();
}
class _LeftWidgetState extends State<LeftWidget> with TickerProviderStateMixin {
List<String> _list = ["Home", "My profile", "Premium", "FAQ"];
List <Widget> _keys = [
HomePage1(), //These are the widgets from different classes.
LoggedInWidget(),
premium(),
faq(),
/*GlobalKey(), //This was available before I made the changes.
GlobalKey(),
GlobalKey(),
GlobalKey()*/
];
int checkIndex = 0;
Offset checkedPositionOffset = Offset(0, 0);
Offset lastCheckOffset = Offset(0, 0);
Offset animationOffset = Offset(0, 0);
Animation _animation;
AnimationController _animationController;
#override
void initState() {
checkIndex = _list.length - 1;
super.initState();
SchedulerBinding.instance.endOfFrame.then((value) {
calcuteCheckOffset();
addAnimation();
});
}
void calcuteCheckOffset() {
lastCheckOffset = checkedPositionOffset;
RenderBox renderBox = _keys[checkIndex].currentContext.findRenderObject(); //This is where the first error occurs.
Offset widgetOffset = renderBox.localToGlobal(Offset(0, 0));
Size widgetSise = renderBox.size;
checkedPositionOffset = Offset(widgetOffset.dx + widgetSise.width,
widgetOffset.dy + widgetSise.height);
}
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
Container(
width: 50,
decoration: BoxDecoration(
color: Color(0xff000000),
borderRadius: BorderRadius.circular(30),
),
child: Column(
children: _buildList(),
),
),
Positioned(
top: animationOffset.dy,
left: animationOffset.dx,
child: CustomPaint(
painter: CheckPointPainter(Offset(10, 0)),
),
)
],
),
);
}
List<Widget> _buildList() {
List<Widget> _widget_list = [];
_widget_list.add(Padding(
padding: EdgeInsets.only(
top: 50,
),
child: Icon(
Icons.settings,
color: Colors.white,
size: 30,
),
));
for (int i = 0; i < _list.length; i++) {
_widget_list.add(Expanded(
child: GestureDetector(
onTap: () {
indexChecked(i);
},
child: VerticalText(
_list[i],
_keys[i], //This is where the second error occurs.
checkIndex == i &&
(_animationController != null &&
_animationController.isCompleted))),
));
}
_widget_list.add(Padding(
padding: EdgeInsets.only(
top: 50,
bottom: 50,
),
child: Image(image: AssetImage('assets/images/Voix.png')),
));
return _widget_list;
}
void indexChecked(int i) {
if (checkIndex == i) return;
setState(() {
checkIndex = i;
calcuteCheckOffset();
addAnimation();
});
}
void addAnimation() {
_animationController =
AnimationController(duration: Duration(milliseconds: 300), vsync: this)
..addListener(() {
setState(() {
animationOffset =
Offset(checkedPositionOffset.dx, _animation.value);
});
});
_animation = Tween(begin: lastCheckOffset.dy, end: checkedPositionOffset.dy)
.animate(CurvedAnimation(
parent: _animationController, curve: Curves.easeInOutBack));
_animationController.forward();
}
}
class CheckPointPainter extends CustomPainter {
double pointRadius = 5;
double radius = 30;
Offset offset;
CheckPointPainter(this.offset);
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..style = PaintingStyle.fill;
double startAngle = -math.pi / 2;
double sweepAngle = math.pi;
paint.color = Color(0xff000000);
canvas.drawArc(
Rect.fromCircle(center: Offset(offset.dx, offset.dy), radius: radius),
startAngle,
sweepAngle,
false,
paint);
paint.color = Color(0xffffffff);
canvas.drawCircle(
Offset(offset.dx - pointRadius / 2, offset.dy - pointRadius / 2),
pointRadius,
paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class VerticalText extends StatelessWidget {
String name;
bool checked;
GlobalKey globalKey;
VerticalText(this.name, this.globalKey, this.checked);
#override
Widget build(BuildContext context) {
return RotatedBox(
key: globalKey,
quarterTurns: 3,
child: Text(
name,
style: TextStyle(
color: checked ? Color(0xffffffff) : Colors.grey,
fontSize: 16,
),
),
);
}
}
class RightWidget extends StatefulWidget {
#override
_RightWidgetState createState() => _RightWidgetState();
}
class _RightWidgetState extends State<RightWidget>
with TickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 5);
}
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(
left: 15,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50, left: 20),
child: Text(
"Voix Home",
style: TextStyle(
color: Colors.black,
fontSize: 25,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 15, left: 10),
child: SizedBox(
height: 30,
child: TabBar(
isScrollable: true,
unselectedLabelColor: Colors.black,
labelColor: Color(0xffffffff),
controller: _tabController,
indicator: BoxDecoration(
color: Color(0xff9e9e9e),
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
),
),
tabs: <Widget>[
Tab(
text: "Flash",
),
Tab(
text: "Magazine",
),
Tab(
text: "Newspaper",
),
Tab(
text: "Kiddos",
),
Tab(
text: "Editorial",
),
],
),
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: <Widget>[
TravelWidget(),
HomeScreen(),
News(),
Kiddos(),
RightBody(),
// RightBody(),
],
),
)
],
),
);
}
}
class RightBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(
left: 15,
),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
top: 20,
),
child: Text(
"Flash!",
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 220,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: new DecorationImage(
image: new AssetImage('assets/images/bottom1.jpg'),
fit: BoxFit.cover,
),
boxShadow: [
BoxShadow(
spreadRadius: 5,
blurRadius: 5,
offset: Offset(1, 2),
color: Color(0x33757575),
),
],
),
),
Container(
width: 220,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
boxShadow: [
BoxShadow(
spreadRadius: 5,
blurRadius: 5,
offset: Offset(1, 2),
color: Color(0x33757575),
),
],
),
),
],
),
),
],
),
);
}
}
class TravelWidget extends StatelessWidget {
List<TravelBean> _list = TravelBean.generateTravelBean();
#override
Widget build(BuildContext context) {
return PageView.builder(
controller: PageController(viewportFraction: 0.9),
itemBuilder: (context, index) {
var bean = _list[index];
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return DetailPage(bean);
}));
},
child: Hero(
tag: bean.url,
child: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 30, right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Image.asset(
bean.url,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
),
),
Positioned(
bottom: 80,
left: 15,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Material(
color: Colors.transparent,
child: Text(
bean.location,
style: TextStyle(
color: Colors.black54,
fontSize: 15,
),
),
),
Material(
color: Colors.transparent,
child: Text(
bean.name,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
],
),
),
Positioned(
bottom: 0,
right: 30,
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Icons.arrow_forward,
color: Colors.white,
size: 30,
),
),
)
],
),
),
);
},
itemCount: _list.length,
);
}
}
At the beginning, when I leave the list _keys to be of the type GlobalKey and don't comment out the following 4 GlobalKeys I get the output but the side menu bar won't work.
This is my application with GlobalKeys in place of those Widgets
I want those corresponding pages to display when clicked on. But that render object just switches between the options and the same page is displayed.
So kindly help me out.
PS : As said earlier I'm new to flutter, so kindly don't mistake me if I had something wrong.
I suggest you check about flutter state management, especially Mobx with Provider, it will be kind easier for you.

Nested Gesture Does not change on Tap

I am currently working on the ui stuff for the appliction, so the thing is i have one gesture as a parent that swipes up and down and based on it the position of the widgets gets changed but the problem is the child gesture does not get any precedence when tapped on it it gives the precedence. So my tree structure is Pageview.builder which has single widget with topmost parent as Gesturedetector and the children accrodingly, Can any one tell me what i am doing wrong or any improvements to get the gesture for each.
Below is the sample code that i have been working on:
import 'dart:math';
import 'package:LocationAnimation/Model/device_model.dart';
import 'package:LocationAnimation/SplashPage/splash_page.dart';
import 'package:LocationAnimation/widgets/device_function_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'Model/device_model.dart' as devices;
import 'Model/locations_model.dart' as locations;
import 'extensions/capitalize.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HAL',
home: MyHomePage(),
);
}
}
class SampleList {
final String locationName;
SampleList({this.locationName});
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final _controller = new PageController();
final _kArrowColor = Colors.black.withOpacity(0.8);
bool _isSwipe = false;
bool _isLoading = false;
var list = [
SampleList(locationName: 'Living Room'),
SampleList(locationName: 'Bed Room'),
SampleList(locationName: 'Back Porch Lights'),
SampleList(locationName: 'Basement Porch Lights'),
SampleList(locationName: 'Sample Room'),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: _isSwipe
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return LocationDetails(
isLoading: _isLoading,
item: list[index],
onSwipeDown: () {
setState(() {
_isSwipe = false;
});
},
onSwipeUp: () {
setState(() {
_isSwipe = true;
});
},
);
},
),
],
),
),
);
}
}
class LocationDetails extends StatefulWidget {
final bool isLoading;
SampleList item;
final Function() onSwipeUp;
final Function() onSwipeDown;
LocationDetails(
{Key key, this.item, this.onSwipeUp, this.onSwipeDown, this.isLoading})
: super(key: key);
#override
_LocationDetailsState createState() => _LocationDetailsState();
}
class _LocationDetailsState extends State<LocationDetails> {
DragStartDetails startVerticalDragDetails;
DragUpdateDetails updateVerticalDragDetails;
bool moveWidget = false;
bool dismissSwipeText = true;
bool _isRotate = false;
int currentSelectedIndex = 0;
bool ignoreChildGestures = true;
bool _isSwpie = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: GestureDetector(
onTap: () {
print('Tap');
},
onVerticalDragStart: (dragDetails) {
startVerticalDragDetails = dragDetails;
},
onVerticalDragUpdate: (dragDetails) {
updateVerticalDragDetails = dragDetails;
},
onVerticalDragEnd: (endDetails) {
double dx = updateVerticalDragDetails.globalPosition.dx -
startVerticalDragDetails.globalPosition.dx;
double dy = updateVerticalDragDetails.globalPosition.dy -
startVerticalDragDetails.globalPosition.dy;
double velocity = endDetails.primaryVelocity;
//Convert values to be positive
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (velocity < 0) {
widget.onSwipeUp();
print('drag up');
setState(() {
moveWidget = true;
_isSwpie = true;
});
} else {
widget.onSwipeDown();
print(' drag down');
setState(() {
moveWidget = false;
_isSwpie = false;
});
}
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.8), BlendMode.srcOver),
image: /* moveWidget
? */
AssetImage(
'Assets/backgroundImage.jpg',
),
/* : NetworkImage(widget.samplePage.networkImage), */
fit: BoxFit.fill,
),
),
child:
/* widget.isLoading
? Center(
child: CircularProgressIndicator(),
)
: */
Stack(
children: <Widget>[
AnimatedOpacity(
opacity: moveWidget ? 0 : 1,
duration: Duration(microseconds: 100),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Icon(
Icons.power_settings_new,
color: Colors.white,
size: 30,
),
Icon(
Icons.more_horiz,
color: Colors.white,
size: 25,
)
],
),
Row(
children: <Widget>[
Column(
children: <Widget>[
Text(
'Inside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
SizedBox(
width: 10,
),
Column(
children: <Widget>[
Text(
'Outside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
],
)
],
),
),
),
AnimatedPositioned(
onEnd: () {
setState(() {
dismissSwipeText = !dismissSwipeText;
//print(dismissSwipeText);
});
},
curve: Curves.ease,
duration: Duration(milliseconds: 700),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.18,
left: 10.0,
right: 0.0,
top: moveWidget
? 50
: MediaQuery.of(context).size.height * 0.75,
child: AnimatedOpacity(
opacity: dismissSwipeText ? 1 : 0,
duration: Duration(milliseconds: 500),
child: Text(
'Swipe up to customize',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 700),
onEnd: () {
setState(() {
_isSwpie = true;
});
},
left: 10,
top: moveWidget
? 80
: MediaQuery.of(context).size.height * 0.80,
child: Container(
width: MediaQuery.of(context).size.width * 0.97,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 0;
});
},
child: Container(
width: MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 0
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Lights',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 1;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 1
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Applicanes',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 2;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 2
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Sensors',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
Container(
width:
MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[900],
),
child: Center(
child: Text(
'Doors \n& Locks',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
],
),
SizedBox(
width: 10,
),
],
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
],
)),
),
),
),
);
}
}
You can add Color to the last AnimatedPositioned which use text widget.item.locationName in your code, like:
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Container(
color: Colors.white,
Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
You will see a white screen (the widget which blocking you) when you scroll up. You can fix it by 2 ways
Change the bottom 10 to a larger number
Move this part of AnimatedPositioned to Top of the Stack widget
The Nested Gesture should work probably as you expected.
First of All you are using multiple Scaffold in a single page which is not recommended.
And remove the unwanted widgets from your tree which will help you to debug a way more better level. And Next you can try with passing a Callback function from parent to child which can eventually solve your problem

Categories

Resources