This is my code, in which I am playing a video. Now I want to stop(pause) video whenever I am switching the page. Sometime the code is working fine but some time audio of video is coming but video page is not opening. I am beginner in flutter. I have tried to pause the video before switching but unfortunately none on my logic has worked. As per my experience this scenario is coming when video is buffering, and I switched the page.
final feedViewModel = GetIt.instance<FeedViewModel>();
int currentIndex = -1;
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _pageController = 0;
List<Widget> _pages = [FeedScreen(), DiscoverPage(), InboxPage(), MePage()];
counter(int index) {
if (currentIndex >= 0) {
try {
if (feedViewModel.listVideos == null) {
final feed = _FeedScreenState();
if (index == 0) {
feed.load("For you");
}
} else {
feedViewModel.listVideos[currentIndex].controller.pause();
feedViewModel.listVideos = null;
feedViewModel.controller.dispose();
feedViewModel.controller=null;
super.dispose();
}
} catch (e) {
feedViewModel.listVideos = null;
final feed = _FeedScreenState();
if (index == 0) {
feed.load("For you");
}
}
}
_pageController = index;
}
#override
Widget build(BuildContext context) {
// Constants.pref.setBool("loggedIn", true);
return ResponsiveBuilder(
builder: (BuildContext context, SizingInformation sizingInformation) {
return Scaffold(
bottomNavigationBar: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
color: Colors.black,
height: sizingInformation.localWidgetSize.height * 0.08,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
onTap: () {
setState(() {
counter(0);
});
},
child: _navBarItem(
title: "Home",
icon: Icons.home,
),
),
InkWell(
onTap: () {
setState(() {
counter(1);
});
},
child: _navBarItem(
title: "Discover",
icon: Icons.search,
),
),
InkWell(
onTap: () async {
if (Constants.pref.getBool("loggedIn") == true) {
try {
if (currentIndex >= 0) {
try {
if (feedViewModel.listVideos != null) {
if (feedViewModel.listVideos[currentIndex]
.controller.value.isPlaying) {
feedViewModel
.listVideos[currentIndex].controller
.pause();
feedViewModel.listVideos = null;
feedViewModel.controller.dispose();
feedViewModel.controller=null;
super.dispose();
}
}
} catch (e) {}
}
} catch (e) {
print(e.toString());
}
final videoPath = await Navigator.of(context)
.pushNamed(CAMERA_SCREEN);
/* Navigator.push(
context,
MaterialPageRoute(
// builder: (_) => Video()
builder: (_) => HomeScreen2(null)
// builder: (_) => AddVideoPage()
));*/
} else {
toast("Please login/sign up");
}
},
child: Container(
margin: EdgeInsets.only(top: 10),
width: 50,
height: sizingInformation.localWidgetSize.height * 0.07,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: Container(
width: 20,
height: sizingInformation.localWidgetSize.height *
0.05,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10)),
color: Colors.blue),
),
),
Align(
alignment: Alignment.topRight,
child: Container(
width: 20,
height: sizingInformation.localWidgetSize.height *
0.05,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10)),
color: Colors.red),
),
),
Align(
alignment: Alignment.topCenter,
child: Container(
width: 40,
height: sizingInformation.localWidgetSize.height *
0.05,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10)),
color: Colors.white),
child: Icon(
Icons.add,
color: Colors.black,
),
),
)
],),),),
InkWell(
onTap: () {
setState(() {
counter(2);
});
},
child: _navBarItem(
title: "Notification",
icon: Icons.message,
),
),
InkWell(
onTap: () {
setState(() {
counter(3);
});
},
child: _navBarItem(
title: "Profile",
icon: Icons.person,
),
),
],
),
),
// body: Constants.pref.getBool("loggedIn") == true && _pageController==4
// ? _pages[_pageController]
// : ProfileApp());
body: _pages[_pageController]);
},
);
}
Widget _navBarItem({String title, IconData icon}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Icon(icon), Text(title)],
);
}
toast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1);
}
}
class FeedScreen extends StatefulWidget {
// FeedScreen({Key key}) : super(key: key);
#override
_FeedScreenState createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen>with SingleTickerProviderStateMixin {
AnimationController _animationController;
int _followingForYouController = 1;
FullScreenDialog _myDialog;
#override
void initState() {
_animationController =
AnimationController(vsync: this, duration: Duration(seconds: 8));
_animationController.repeat();
load("For you");
super.initState();
}
Future<bool> _onWillPop() async {
if (currentIndex >= 0) {
if (feedViewModel.listVideos != null) {
feedViewModel.listVideos[currentIndex].controller.pause();
feedViewModel.listVideos = null;
feedViewModel.controller.dispose();
feedViewModel.controller=null;
super.dispose();
}
}
}
#override
Widget build(BuildContext context) {
return ViewModelBuilder<FeedViewModel>.reactive(
disposeViewModel: false,
builder: (context, model, child) => videoScreen(),
viewModelBuilder: () => feedViewModel);
}
Widget videoScreen() {
return WillPopScope(
onWillPop: _onWillPop,
child: ResponsiveBuilder(
builder: (BuildContext context, SizingInformation sizingInformation) {
return Padding(
padding: const EdgeInsets.all(1),
child: Scaffold(
backgroundColor: GetIt.instance<FeedViewModel>().actualScreen == 0
? Colors.black
: Colors.white,
body: Stack(
children: [
PageView.builder(
itemCount: 1,
onPageChanged: (value) {
print(value);
if (value == 1)
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.dark);
else
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light);
},
itemBuilder: (context, index) {
return scrollFeed(sizingInformation);
})
],
),
));
}),
);
}
Widget scrollFeed(SizingInformation sizingInformation) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(child: feedVideos(sizingInformation)),
],
);
}
Widget feedVideos(SizingInformation sizingInformation) {
return feedViewModel.listVideos != null
? Scaffold(body: videoPage(sizingInformation))
: Center(child: CircularProgressIndicator());
}
Widget videoPage(SizingInformation sizingInformation) {
return Stack(
children: [
PageView.builder(
controller: PageController(
initialPage: 0,
viewportFraction: 1,
),
itemCount: feedViewModel.listVideos.length,
onPageChanged: (index) {
index = index % (feedViewModel.listVideos.length);
feedViewModel.changeVideo(index);
},
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
currentIndex = index;
index = index % (feedViewModel.listVideos.length);
return videoCard(
feedViewModel.listVideos[index], index, sizingInformation);
},
),
followingForYou(),
],
);
}
Widget videoCard(
Video video, int index, SizingInformation sizingInformation) {
return Stack(
children: [
video.controller != null
? GestureDetector(
onTap: () {
if (video.controller.value.isPlaying) {
video.controller.pause();
} else {
video.controller.play();
}
},
child: SizedBox.expand(
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: video.controller.value.size?.width ?? 0,
height: video.controller.value.size?.height ?? 0,
child: VideoPlayer(video.controller),
),
)),
)
: Container(
color: Colors.black,
child: Center(
child: Text("Loading..."),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
VideoDescription(
video.id, video.user, video.videoTitle, video.songName),
_rightWidget(video, index),
// _rightSideButtonsWidgets(index),
// _textDataWidgetBottom(sizingInformation, index)
],
),
SizedBox(height: 20)
],
),
],
);
}
#override
void dispose() {
try {
feedViewModel.controller.dispose();
feedViewModel.controller=null;
super.dispose();
} catch (e) {
print(e.toString());
}
}
load(String type) async {
feedViewModel.listVideos = await getVideoList(type);
setState(() {
feedViewModel.loadVideo(0);
// feedViewModel.loadVideo(1);
});
}
Future<List<Video>> getVideoList(String type) async {
var videoList = <Video>[];
final body = {
"username": Constants.pref.getString("profileId"),
"Type": type,
};
var jsonObj = json.encode(body);
var response = await http.post('https://ssca-api.appspot.com/act/video/',
headers: {"api-Key": "NkHb13BxRBiZ0JSyxLbAU"}, body: jsonObj);
print("${response.request}"); //200 if successful
print("http status: ${response.statusCode}"); //200 if successful
print("http Request: ${jsonObj}"); //200 if successful
print("http Response: ${response.body}");
var data = json.decode(response.body);
// data = jsonDecode(response.body);
for (int i = 0; i < data["video"].length; i++) {
Video video = new Video();
video.id = data["video"][i]["id"];
video.user = data["video"][i]["profileId"];
video.userPic = data["video"][i]["image"];
video.videoTitle = data["video"][i]["description"];
video.songName = "Music name is here";
video.likes = data["video"][i]["liked"];
video.comments = data["video"][i]["comment"];
video.url = data["video"][data["video"].length-1]["video"];
// video.url = data["video"][i]["video"];
video.isLiked = data["video"][i]["isLiked"];
if (data["video"][i]["followstatus"] == 0) {
video.following = false;
} else {
video.following = true;
}
video.isLiked = data["video"][i]["isLiked"];
videoList.add(video);
}
return videoList;
}
toast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1);
}
// Full dimensions of an action
static const double ActionWidgetSize = 60.0;
// The size of the icon showen for Social Actions
static const double ActionIconSize = 35.0;
// The size of the share social icon
static const double ShareActionIconSize = 25.0;
// The size of the profile image in the follow Action
static const double ProfileImageSize = 50.0;
// The size of the plus icon under the profile image in follow action
static const double PlusIconSize = 20.0;
LinearGradient get musicGradient => LinearGradient(colors: [
Colors.grey[800],
Colors.grey[900],
Colors.grey[900],
Colors.grey[800]
], stops: [
0.0,
0.4,
0.6,
1.0
], begin: Alignment.bottomLeft, end: Alignment.topRight);
Widget _rightWidget(Video video, int index) {
return Container(
width: 100.0,
child: Column(mainAxisSize: MainAxisSize.min, children: [
_getFollowAction(index),
_likeWidget(index),
GestureDetector(
onTap: () {
if (Constants.pref.getBool("loggedIn") == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CommentList(feedViewModel.listVideos[index].id)));
} else {
toast("Please login/sign up");
}
},
child: Container(
margin: EdgeInsets.only(top: 15.0),
width: 60.0,
height: 60.0,
child: Column(children: [
Icon(FontAwesomeIcons.comment,
size: 35.0, color: Colors.grey[300]),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Text(video.comments,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 12.0)),
)
])),
),
GestureDetector(
onTap: () {
// _shareImageAndText(video);
Share.share('check out my video ' + video.url);
},
child: Container(
margin: EdgeInsets.only(top: 15.0),
width: 60.0,
height: 60.0,
child: Column(children: [
Icon(FontAwesomeIcons.share,
size: 25.0, color: Colors.grey[300]),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Text('Share',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 12.0)),
)
])),
),
GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => _myDialog =
new FullScreenDialog(feedViewModel.listVideos[index].id),
fullscreenDialog: true,
));
},
child: Container(
margin: EdgeInsets.only(top: 15.0),
width: 60.0,
height: 60.0,
child: Column(children: [
Icon(FontAwesomeIcons.angry,
size: 25.0, color: Colors.grey[300]),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Text('Report',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 12.0)),
)
])),
),
CircleImageAnimation(
child: _getMusicPlayerAction(video.userPic),
)
]),
);
}
Widget _likeWidget(int index) {
return GestureDetector(
onTap: () {
if (Constants.pref.getBool("loggedIn") == true) {
setState(() {
if (feedViewModel.listVideos[index].isLiked) {
feedViewModel.listVideos[index].isLiked = false;
} else {
feedViewModel.listVideos[index].isLiked = true;
}
final body = {
"username": Constants.pref.getString("profileId"),
"videoId": feedViewModel.listVideos[index].id,
"like": feedViewModel.listVideos[index].isLiked,
};
ApiService.like(body).then((success) {
if (success.statusCode == 200) {
var response = json.decode(success.body);
if (response["response"]["confirmation"] != 0) {
feedViewModel.listVideos[index].likes =
response["response"]["TotalLiked"];
} else {
ShowAlertDialog(context, response["success"]["message"]);
}
} else {
ShowAlertDialog(context, ParameterConstant.STATUS);
}
});
});
} else {
toast("Please login/sign up");
}
},
child: Container(
margin: EdgeInsets.only(top: 15.0),
width: 60.0,
height: 60.0,
child: Column(children: [
Icon(
FontAwesomeIcons.solidHeart,
size: 35.0,
color:
feedViewModel.listVideos[index].isLiked ? Colors.red : null,
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Text(feedViewModel.listVideos[index].likes,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 12.0)),
)
])),
);
}
Widget _getFollowAction(int index) {
return GestureDetector(
onTap: () {
if (Constants.pref.getBool("loggedIn") == true) {
setState(() {
if (feedViewModel.listVideos[index].following) {
feedViewModel.listVideos[index].following = false;
} else {
feedViewModel.listVideos[index].following = true;
}
final body = {
"profileId": Constants.pref.getString("profileId"),
"followupId": feedViewModel.listVideos[index].user,
};
ApiService.follow(body).then((success) {
if (success.statusCode == 200) {
var response = json.decode(success.body);
// if (response["confirmation"] != 0) {
/* if (feedViewModel.listVideos[index].following) {
feedViewModel.listVideos[index].following = false;
} else {
feedViewModel.listVideos[index].following = true;
}*/
// } else {
// ShowAlertDialog(context, response["message"]);
// }
} else {
ShowAlertDialog(context, ParameterConstant.STATUS);
}
});
});
} else {
toast("Please login/sign up");
}
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
width: 60.0,
height: 60.0,
child: Stack(children: [
_getProfilePicture(feedViewModel.listVideos[index].userPic),
_getPlusIcon(index)
])),
);
}
Widget _getProfilePicture(userPic) {
return Positioned(
left: (ActionWidgetSize / 2) - (ProfileImageSize / 2),
child: Container(
padding: EdgeInsets.all(1.0),
// Add 1.0 point padding to create border
height: ProfileImageSize,
// ProfileImageSize = 50.0;
width: ProfileImageSize,
// ProfileImageSize = 50.0;
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(ProfileImageSize / 2)),
// import 'package:cached_network_image/cached_network_image.dart'; at the top to use CachedNetworkImage
child: ClipRRect(
borderRadius: BorderRadius.circular(10000.0),
child: CachedNetworkImage(
imageUrl: userPic,
placeholder: (context, url) =>
new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
))));
}
Widget _getPlusIcon(int index) {
return Positioned(
bottom: 0,
left: ((ActionWidgetSize / 2) - (PlusIconSize / 2)),
child: Container(
width: PlusIconSize, // PlusIconSize = 20.0;
height: PlusIconSize, // PlusIconSize = 20.0;
decoration: BoxDecoration(
color: Color.fromARGB(255, 255, 43, 84),
borderRadius: BorderRadius.circular(15.0)),
child: Icon(
feedViewModel.listVideos[index].following
? Icons.remove
: Icons.add,
color: Colors.white,
size: 20.0,
)),
);
// import_contacts, clear,forward,gesture
}
Widget _getMusicPlayerAction(userPic) {
return Container(
margin: EdgeInsets.only(top: 10.0),
width: ActionWidgetSize,
height: ActionWidgetSize,
child: Column(children: [
Container(
padding: EdgeInsets.all(11.0),
height: ProfileImageSize,
width: ProfileImageSize,
decoration: BoxDecoration(
gradient: musicGradient,
borderRadius: BorderRadius.circular(ProfileImageSize / 2)),
child: ClipRRect(
borderRadius: BorderRadius.circular(10000.0),
child: CachedNetworkImage(
imageUrl: userPic,
placeholder: (context, url) =>
new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
))),
]));
}
TextStyle _textStyleFollowingForYou(Color color) {
return TextStyle(fontSize: 18, color: color, fontWeight: FontWeight.w500);
}
Widget followingForYou() {
return SafeArea(
child: Container(
padding: EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
if (Constants.pref.getBool("loggedIn") == true) {
_followingForYouController = 0;
setState(() {
feedViewModel.listVideos[currentIndex].controller
.pause();
feedViewModel.listVideos = null;
load("Following");
});
} else {
toast("Please login/sign up");
}
});
},
child: Text("Following",
style: _textStyleFollowingForYou(
_followingForYouController == 0
? Colors.white
: Colors.white60))),
SizedBox(
width: 15,
),
GestureDetector(
onTap: () {
setState(() {
try {
feedViewModel.listVideos[currentIndex].controller
.pause();
} catch (e) {
print(e.toString());
}
_followingForYouController = 1;
feedViewModel.listVideos = null;
load("For you");
});
},
child: Text("For you",
style: _textStyleFollowingForYou(
_followingForYouController == 1
? Colors.white
: Colors.white60)))
],
),
]),
),
);
}
}
Related
i am adding shuffle() function but the error is showing Another exception was thrown: type 'String' is not a subtype of type 'int' of 'index' is there any solution to put question in shuffle i don't know where to add this shuffle function there was not any error in this project the json files is added with this code
i am adding mydata.shuffle() in this code
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString(assettoload, cache: false),
builder: (context, snapshot) {
List? mydata = json.decode(snapshot.data.toString());
if (mydata == null) {
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
} else {
return quizpage(mydata: mydata);
}
},
);
}
}
class quizpage extends StatefulWidget {
final List mydata;
quizpage({required this.mydata});
#override
_quizpageState createState() => _quizpageState();
}
class _quizpageState extends State<quizpage> {
_quizpageState();
Color colortoshow = Colors.indigoAccent;
int marks = 0;
int i = 1;
bool disableAnswer = false;
// extra varibale to iterate
int timer = 30;
String showtimer = "30";
Map<String, Color> btncolor = {
"a": Colors.indigo.shade900,
"b": Colors.indigo.shade900,
"c": Colors.indigo.shade900,
"d": Colors.indigo.shade900,
};
bool canceltimer = false;
#override
void initState() {
starttimer();
super.initState();
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t) {
setState(() {
if (timer < 1) {
t.cancel();
nextquestion();
} else if (canceltimer == true) {
t.cancel();
} else {
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void nextquestion() {
canceltimer = false;
timer = 30;
setState(() {
if (i < 10) {
i++;
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(marks: marks),
));
}
btncolor["a"] = Colors.indigo.shade900;
btncolor["b"] = Colors.indigo.shade900;
btncolor["c"] = Colors.indigo.shade900;
btncolor["d"] = Colors.indigo.shade900;
disableAnswer = false;
});
starttimer();
}
void checkanswer(String k) {
if (widget.mydata[2][i.toString()] == widget.mydata[1][i.toString()][k]) {
marks = marks + 5;
} else {}
setState(() {
btncolor[k] = colortoshow;
canceltimer = true;
disableAnswer = true;
});
Timer(Duration(seconds: 2), nextquestion);
}
Widget choicebutton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: SizedBox(
height: 60,
width: 400,
child: OutlinedButton(
onPressed: () => checkanswer(k),
child: Text(
widget.mydata[1][i.toString()][k] ?? "",
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: "Alike",
fontSize: 18.0,
),
maxLines: 1,
),
style: OutlinedButton.styleFrom(
side: BorderSide(width: 3.0, color: Colors.indigo.shade900),
backgroundColor: Colors.transparent,
shape: const StadiumBorder()),
),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () async {
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Quizstar",
),
content: Text("You Can't Go Back At This Stage."),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Ok',
),
)
],
));
},
child: SafeArea(
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
width: 500,
height: 200,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/canva4.png",
),
fit: BoxFit.cover,
),
),
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
widget.mydata[0][i.toString()],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 20.0,
fontFamily: "Quando",
),
),
),
),
Divider(height: 10, color: Colors.black, thickness: 10),
Expanded(
flex: 6,
child: AbsorbPointer(
absorbing: disableAnswer,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choicebutton('a'),
choicebutton('b'),
choicebutton('c'),
choicebutton('d'),
],
),
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 35.0,
fontWeight: FontWeight.w700,
fontFamily: 'Times New Roman',
),
),
),
),
),
],
),
),
),
);
}
}
I'm trying to accomplished something like had been issued here : Flutter single `DataCell` color
I want to grey out the cell to let user know that was supposed to leave blank. Currently I manage to fill the height of datacell but the width.
my code snippet:
_data[i][newColumn] = Container(
width: double.infinity,
height: double.infinity,
color: Colors.grey,
child: Text(''));
Result: Last cell at the most right which fill up height space only:
full code :
import 'dart:convert';
import 'dart:ui';
import 'package:http/http.dart';
import 'package:flutter/material.dart';
class InspectionSheet extends StatefulWidget {
const InspectionSheet({Key? key}) : super(key: key);
#override
State<InspectionSheet> createState() => _InspectionSheetState();
}
class _InspectionSheetState extends State<InspectionSheet> {
GlobalKey<FormState> _formKey = new GlobalKey();
bool validate = false;
TextEditingController ctrlsampleSize = TextEditingController();
final List<Map<String, dynamic>> _data = [
{
//"checkitemID": "0",
"Ballooning No": "1",
"Datatype": "1",
"Specifications": ".325+-0.020",
"Tool": "CALIPER",
"LSL": "0.305",
"Target": "2",
"USL": "0.325",
"Tol-": "0.02",
"Tol+": "0.02",
"Image": "",
"WI": ""
},
{
//"checkitemID": "0",
"Ballooning No": "2",
"Datatype": "2",
"Specifications": ".325+-0.020",
"Tool": "CALIPER",
"LSL": "0.305",
"Target": "2",
"USL": "0.325",
"Tol-": "0.02",
"Tol+": "0.02",
"Image": "",
"WI": ""
},
];
late List<String> _columnNames;
//String _selectedValue = inputList.first;
String _selectedValue = 'PASS';
void startbutton() {
validateEmpty();
if (_formKey.currentState!.validate()) {
addDataCol();
}
}
void validateEmpty() {
//if (_formKey.currentState!.validate()) {
// // If the form is valid, display a snackbar. In the real world,
// // you'd often call a server or save the information in a database.
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Processing Data')),
// );
ctrlsampleSize.text.isEmpty ? validate = false : validate = true;
//}
}
void addDataCol() {
int colNo = int.parse(ctrlsampleSize.text);
if (colNo < 1) {
return;
}
setState(() {
for (var i = 1; i <= colNo; i++) {
_addColumn('Data $i');
}
});
}
void _addColumn(String newColumn) {
if (_columnNames.contains(newColumn)) {
return;
}
setState(() {
for (var i = 0; i <= _data.length - 1; i++) {
if (_data[i]['Datatype'] == '1') {
_data[i][newColumn] = TextFormField();
} else if (_data[i]['Datatype'] == '2') {
_data[i][newColumn] = DropdownButton<String>(
value: _selectedValue,
icon: const Icon(Icons.arrow_drop_down_circle_outlined),
elevation: 16,
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (newValue) {
setState(() {
_selectedValue = newValue!;
});
},
items:
// inputList.map<DropdownMenuItem<String>>((String value) {
// return DropdownMenuItem<String>(
// value: value,
// child: Text(value),
// onTap: () {
// _selectedValue = value;
// },
// );
// }).toList(),
[
DropdownMenuItem(
value: 'PASS',
child: const Text('PASS'),
onTap: () {
_selectedValue = 'PASS';
},
),
DropdownMenuItem(
value: 'FAIL',
child: const Text('FAIL'),
onTap: () {
_selectedValue = 'FAIL';
},
),
DropdownMenuItem(
value: 'UAI',
child: const Text('UAI'),
onTap: () {
_selectedValue = 'UAI';
},
),
DropdownMenuItem(
value: 'NA',
child: const Text('NA'),
onTap: () {
_selectedValue = 'NA';
},
)
]);
} else if (_data[i]['Datatype'] == '3') {
if (newColumn == 'Data 1') {
_data[i][newColumn] = TextButton(
onPressed: () {
_displayTextInputDialog(context);
},
child: const Text('-'));
} else {
_data[i][newColumn] = Container(
width: double.infinity,
height: double.infinity,
color: Colors.grey,
child: Text(''));
}
} else {
_data[i][newColumn] = TextButton(
onPressed: () {
_displayTextInputDialog(context);
},
child: const Text('-'));
}
}
_columnNames.add(newColumn);
});
}
#override
void initState() {
dateInput.text = "";
_columnNames = _data[0].keys.toList();
//set the initial value of text field
super.initState();
//// Start listening to changes.
ctrlsampleSize.addListener(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Form(
child: Row(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 210,
child: Form(
key: _formKey,
child: ListView(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 200,
height: 200,
child: Column(
children: <Widget>[
TextFormField(
controller: ctrlsampleSize,
validator: ((value) {
if (value == null || value.isEmpty) {
return 'Please enter sample size';
}
return null;
}),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Container(
width: 400,
height: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
image: DecorationImage(
image: AssetImage('images/Test1.jpg'),
fit: BoxFit.fill,
)),
),
),
],
),
],
),
),
Container(
child: Container(
child: Center(
child: Row(
// add Column
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 860, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text(
"Total Parameter : 6",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () => startbutton(),
child: const Text('Start'),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Reset'),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Save'),
),
),
],
),
),
)),
Padding(
padding: const EdgeInsets.all(8.0),
child:
//****uncomment if use Provider */
// Container(
// decoration: BoxDecoration(
// border: Border.all(color: Colors.black),
// ),
// child: ConstrainedBox(
// constraints: const BoxConstraints(
// maxHeight: 600,
// maxWidth: 813,
// ),
// child: Column(
// children: [
// Expanded(
// child: ChangeNotifierProvider<CheckItemProvider>(
// create: (context) => CheckItemProvider(),
// child: Consumer<CheckItemProvider>(
// builder: (context, provider, child) {
// provider.getData(context);
// return const Center(
// child: CircularProgressIndicator());
// // when we have the json loaded... let's put the data into a data table widget
// return
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: DataTable(
headingRowHeight: 30,
border: TableBorder.all(
color: Colors.grey,
),
headingRowColor: MaterialStateColor.resolveWith(
(states) => Colors.lightBlue),
headingTextStyle: const TextStyle(
color: Colors.white, fontWeight: FontWeight.w800),
columns: _columnNames.map((columnName) {
return DataColumn(
label: Text(
columnName,
// style: const TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.w600,
// ),
),
);
}).toList(),
rows:
_data // Loops through dataColumnText, each iteration assigning the value to element
.map((row) {
return DataRow(
cells: row.values.map((cellValue) {
try {
return DataCell(
cellValue,
onTap: () {},
);
} catch (e) {
return DataCell(Text(cellValue));
}
;
}).toList());
}).toList(),
),
),
),
//},
// ),
// ),
// ),
// ],
// ),
// ),
// ),
),
],
),
);
}
}
Im using table_calendar package in my project, but ive faced two problems so far :
The calendar doesnt load todays events below the calendar, i would love to hear some ideas how to get this one done.
Even if i put (code below) in tables parameters, it doesnt allow to switch calendar modes.
code for swiching calendar modes for 2nd bullet point of my problems:
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
Just in case, here is the whole code for page which has problems :
class Lecture_graph extends StatefulWidget {
Lecture_graph({Key key}) : super(key: key);
#override
State<Lecture_graph> createState() => myLectureGraph();
}
class myLectureGraph extends State<Lecture_graph>
with TickerProviderStateMixin {
List _selectedEvents;
DateTime _selectedDate = DateTime.now();
Map<DateTime, List<Lecture>> _events;
CalendarController _calendarController;
AnimationController _animationController;
List<Lecture> _lectures;
String coursecode = "";
bool isJoin, isBreaks = false;
bool isLoading = true;
final Map<DateTime, List> _holidays = {
// DateTime(2021, 1, 1): ['New Year\'s Day'],
// DateTime(2021, 2, 14): ['Valentine\'s Day'],
// DateTime(2021, 3, 8): ['Woman\'s Day'],
};
Future<Map<DateTime, List>> getLectures(DateTime _selectedDate) async {
print("getLectures started.");
setState(() {
isLoading = true;
});
Map<DateTime, List<Lecture>> mapFetch = {};
//get saved course
if (coursecode == "" || coursecode == null) {
coursecode = await _checkSavedCourse();
//debug
print('courscode recieved from sharedprefs');
}
//build request URL
var requestURL =
'https://lekcijas.va.lv/lekcijas_android/getMonthLectures.php?date=' +
DateFormat('yyyy-MM').format(_selectedDate) +
(isBreaks ? "&breaks" : "") +
(isJoin ? "&join" : "") +
"&program=" +
coursecode +
"&lang=" +
AppLocalizations.of(context).translate('request_language');
print("Lecture request url : $requestURL");
//wait for response
var response = await http.get(Uri.parse(requestURL));
var data = json.decode(response.body)["result"];
//clear array after each request
if (_lectures != null) _lectures.clear();
try {
//create lectures from json response
_lectures = List<Lecture>.from(data.map((x) => Lecture.fromJson(x)));
} on Exception catch (_) {
print("Error occured getting lectures");
}
_lectures.forEach((element) {
if (mapFetch[element.lecture_date] != null) {
mapFetch[element.lecture_date] += [element];
} else {
mapFetch[element.lecture_date] = [element];
}
});
setState(() {
isLoading = false;
});
print("getLectures finished.");
return mapFetch;
}
Future<void> _saveVales(String key, bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
print("Sharedpref $key is set to $value now");
prefs.setBool(key, value);
}
Future<void> _checkSavedParameters() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
isBreaks = prefs.getBool('lectures_breaks') == null
? false
: prefs.getBool('lectures_breaks');
isJoin = prefs.getBool('lectures_join') == null
? false
: prefs.getBool('lectures_join');
}
Future<String> _checkSavedCourse() async {
//check saved parameters for lecture requests too
await _checkSavedParameters();
SharedPreferences prefs = await SharedPreferences.getInstance();
String _coursecode = prefs.getString('savedCourse');
if (_coursecode == "" || _coursecode == null) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CourseSelectionPage()),
);
return null;
} else {
return _coursecode;
}
}
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
setState(() {
_selectedEvents = events;
});
}
#override
void initState() {
super.initState();
//enable portrait only mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
_selectedEvents = [];
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
}
#override
void dispose() {
_calendarController.dispose();
//unlock orientation mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(coursecode +
" | " +
AppLocalizations.of(context).translate('lectures_title')),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text(
AppLocalizations.of(context).translate('settings')),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
CupertinoSwitch(
value: isJoin,
onChanged: (bool value) {
_saveVales('lectures_join', value);
isJoin = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('join_lectures'))
],
),
SizedBox(height: 10),
Row(
children: [
CupertinoSwitch(
value: isBreaks,
onChanged: (bool value) {
_saveVales('lectures_breaks', value);
isBreaks = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('show_breaks'))
],
),
SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () {
//close popup
Navigator.pop(context);
//close page
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CourseSelectionPage()),
);
},
child: Text(
AppLocalizations.of(context)
.translate('select_course'),
style: TextStyle(color: Colors.lime),
)),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)
.translate('close')),
),
],
);
},
);
},
);
},
)
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
isLoading
? Expanded(child: Center(child: CircularProgressIndicator()))
: _buildTableCalendarWithBuilders(),
const SizedBox(height: 2.0),
Expanded(child: _buildEventList()),
],
),
),
);
}
Widget _buildTableCalendarWithBuilders() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
clipBehavior: Clip.antiAlias,
child: TableCalendar(
locale:
AppLocalizations.of(context).translate('request_language') ==
'lv'
? "lv_LV"
: "en_US",
initialSelectedDay: _selectedDate,
calendarController: _calendarController,
events: _events,
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.scale,
startingDayOfWeek: StartingDayOfWeek.monday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
calendarStyle: CalendarStyle(
outsideDaysVisible: false,
weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
),
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonVisible: false,
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, _) {
return FadeTransition(
opacity:
Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.deepOrange[300],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
),
);
},
todayDayBuilder: (context, date, _) {
return Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.amber[400],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
);
},
markersBuilder: (context, date, events, holidays) {
final children = <Widget>[];
if (events.isNotEmpty) {
children.add(
Positioned(
right: 1,
bottom: 1,
child: _buildEventsMarker(date, events),
),
);
}
if (holidays.isNotEmpty) {
children.add(
Positioned(
right: -2,
top: -2,
child: _buildHolidaysMarker(),
),
);
}
return children;
},
),
onDaySelected: (date, events, holidays) {
_onDaySelected(date, events);
_animationController.forward(from: 0.0);
},
onVisibleDaysChanged: _onVisibleDaysChanged,
),
),
],
);
}
void _onVisibleDaysChanged(
DateTime first, DateTime last, CalendarFormat format) {
_selectedDate = first;
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
print('CALLBACK: _onVisibleDaysChanged');
}
Widget _buildEventsMarker(DateTime date, List events) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _calendarController.isSelected(date)
? Colors.brown[500]
: _calendarController.isToday(date)
? Colors.brown[300]
: Colors.green[400],
),
width: 18.0,
height: 18.0,
child: Center(
child: Text(
'${events.length}',
style: TextStyle().copyWith(
color: Colors.white, fontSize: 12.0, fontWeight: FontWeight.w900),
),
),
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
Widget _buildEventList() {
return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}
void displayDialog(Lecture selectedLecture, BuildContext ctx) {
//if selected lecture is a break
if (!selectedLecture.lecturer.isEmpty &&
!selectedLecture.classroom.isEmpty &&
!selectedLecture.programs.isEmpty) {
showDialog(
barrierDismissible: true,
context: ctx,
builder: (BuildContext context) => new AlertDialog(
title: new Text(AppLocalizations.of(context).translate('info_title')),
content: new Wrap(
runSpacing: 5,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_time') +
selectedLecture.start +
" - " +
selectedLecture.end),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecturer') +
selectedLecture.lecturer),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_classroom') +
selectedLecture.classroom),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecture') +
selectedLecture.lecture),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_date') +
DateFormat('yyyy-MM-dd')
.format(selectedLecture.lecture_date)
.toString()),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_programs') +
selectedLecture.programs),
),
],
),
actions: [
new TextButton(
child: Text(AppLocalizations.of(context).translate('close')),
onPressed: () => Navigator.pop(context, true),
),
],
),
);
}
}
}
In case someone wants to see JSON request results, here is the link for that.
So i got this fixed, adding this to TableCalendar() parameters:
(i called selectedEvents variable update once calendar finished building (because im showing CircularProgressIndicator instead of it while i recieve data from http request) )
onCalendarCreated: (d1, d2, cf){WidgetsBinding.instance
.addPostFrameCallback((_) => _onDaySelected(_selectedDate, _events[_selectedDate]));},
changed _onDaySelected method to:
(here i change selectedday variable to day recieved from calendar click and change state of selectedEvents, replacing them with total_events_map[key_which_is_selectedDay])
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
//dates are used with nulled time
_selectedDate = DateTime(day.year, day.month, day.day, 0, 0, 0);
setState(() {
_selectedEvents = _events[_selectedDate];
});
}
and changed _buildEventList() to this :
(so if selectedEvents are empty, it tells user so, if not, generates a list of items from selectedEvents)
Widget _buildEventList() {
if(_selectedEvents == null)
return ListView(
children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(8.0),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(tr('nothing_planned'),
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
),
),
],
);
else return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:camera/camera.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shoutout_studio/views/camera/profile_screen.dart';
import 'package:video_player/video_player.dart';
class CameraScreen extends StatefulWidget {
#override
_CameraScreenState createState() => _CameraScreenState();
}
bool isRecording = false;
class _CameraScreenState extends State<CameraScreen>
with WidgetsBindingObserver {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
CameraController controller;
List cameras;
int selectedCameraIdx;
XFile videoFile;
XFile imageFile;
VideoPlayerController videoController;
VoidCallback videoPlayerListener;
bool enableAudio = true;
#override
void initState() {
super.initState();
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
setState(() {
selectedCameraIdx = 0;
});
_initCameraController(cameras[selectedCameraIdx]).then((void v) {});
} else {
print('NO Camera Available');
}
}).catchError((err) {
print('Error: $err.code\nError Message: $err.message');
});
}
Future _initCameraController(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(cameraDescription, ResolutionPreset.high);
controller.addListener(() {
if (mounted) {
setState(() {});
}
if (controller.value.hasError) {
print('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
child: _cameraPreviewWidget(),
),
Container(
height: MediaQuery.of(context).size.height * 0.27,
color: Colors.black.withOpacity(0.58),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: size.height * 0.015,
right: size.width * 0.05,
left: size.width * 0.05,
),
child: Row(
children: [
Column(
children: [
SizedBox(
height: size.height * 0.01,
),
GestureDetector(
onTap: () {
Navigator.of(context).pop();
controller.dispose();
},
child: Image(
height: size.height * 0.03,
image: AssetImage('assets/icons/back_arrow.png'),
),
),
],
),
SizedBox(
width: size.width * 0.05,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: size.height * 0.02,
),
Text(
'Identity Verification Script',
textAlign: TextAlign.center,
style: GoogleFonts.quicksand(
fontSize: size.width * 0.048,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
SizedBox(
height: size.height * 0.01,
),
Container(
height: 3,
width: size.width * 0.2,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xffFD0C92),
Color(0xf0FD0C92),
Colors.yellow[200],
]),
),
)
],
),
],
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Hi',
textAlign: TextAlign.center,
style: GoogleFonts.quicksand(
color: Colors.white,
fontSize: size.width * 0.04,
),
),
),
],
),
),
Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.52,
left: MediaQuery.of(context).size.width * 0.84,
),
child: _cameraTogglesRowWidget(),
),
Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.8,
),
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.58),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60.0),
topRight: Radius.circular(60.0),
),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
Text(
'Replay',
style: GoogleFonts.quicksand(
color: Colors.white,
),
),
GestureDetector(
child: Container(
height: size.height * 0.08,
width: size.width * 0.13,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/replay.png',
),
fit: BoxFit.fill,
),
),
),
onTap: () {
//_startVideoPlayer();
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: _captureControlRowWidget(context),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
Text(
'Upload',
style: GoogleFonts.quicksand(
color: Colors.white,
),
),
GestureDetector(
child: Container(
height: size.height * 0.08,
width: size.width * 0.13,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/upload.png',
),
fit: BoxFit.fill,
),
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfilePicture(),
),
);
controller.dispose();
},
),
],
),
),
],
),
),
),
),
SizedBox(height: 20.0)
],
),
);
}
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: CameraPreview(controller),
);
}
Widget _captureControlRowWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
Text(
'Record',
style: GoogleFonts.quicksand(
color: Colors.white,
),
),
GestureDetector(
child: CircleAvatar(
backgroundColor: Colors.white,
radius: 30,
child: Icon(
isRecording ? Icons.pause : Icons.fiber_manual_record_rounded,
color: Colors.red,
size: 35,
),
),
onTap: () => isRecording
? onStopButtonPressed()
: onVideoRecordButtonPressed(),
),
],
),
),
);
}
Widget _cameraTogglesRowWidget() {
if (cameras == null || cameras.isEmpty) {
return Spacer();
}
return Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: GestureDetector(
onTap: () => _onSwitchCamera(),
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/reverse.png',
),
fit: BoxFit.fill,
),
),
),
),
),
);
}
void _onSwitchCamera() {
selectedCameraIdx =
selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0;
CameraDescription selectedCamera = cameras[selectedCameraIdx];
_initCameraController(selectedCamera);
}
void onVideoRecordButtonPressed() {
isRecording = true;
startVideoRecording().then((_) {
if (mounted) setState(() {});
});
}
void onStopButtonPressed() {
isRecording = false;
stopVideoRecording().then((file) {
if (mounted) setState(() {});
if (file != null) {
showInSnackBar('Video recorded to ${file.path}');
videoFile = file;
}
}, onError: (e) {
print(e);
});
}
Future<void> startVideoRecording() async {
if (!controller.value.isInitialized) {
showInSnackBar('Error: select a camera first.');
return;
}
if (controller.value.isRecordingVideo) {
// A recording is already started, do nothing.
return;
}
try {
await controller.startVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return;
}
}
Future<XFile> stopVideoRecording() async {
if (!controller.value.isRecordingVideo) {
return null;
}
try {
return controller.stopVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
}
Future<void> _startVideoPlayer() async {
final VideoPlayerController vController =
VideoPlayerController.file(File(videoFile.path));
videoPlayerListener = () {
if (videoController != null && videoController.value.size != null) {
// Refreshing the state to update video player with the correct ratio.
if (mounted) setState(() {});
videoController.removeListener(videoPlayerListener);
}
};
vController.addListener(videoPlayerListener);
await vController.setLooping(false);
await vController.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
imageFile = null;
videoController = vController;
});
}
await vController.play();
}
void showInSnackBar(String message) {
// ignore: deprecated_member_use
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
}
void _showCameraException(CameraException e) {
String errorText = 'Error: ${e.code}\nError Message: ${e.description}';
print(errorText);
print('Error: ${e.code}\n${e.description}');
}
}
I am creating a camera recording page and this is what I have done so for but I am getting this error but I don't know how to solve this. I thought that It was due to the camera preview widget but I had searched for this exception and find this link incorrect use of parent data widget. expanded widgets must be placed inside flex widgets
In particular, when using a Stack you can't position children relative to their size or the stack's own size.
Each child of a Stack widget is either positioned or non-positioned. Positioned children are those wrapped in a Positioned widget that has at least one non-null property. The stack sizes itself to contain all the non-positioned children, which are positioned according to alignment (which defaults to the top-left corner in left-to-right environments and the top-right corner in right-to-left environments). The positioned children are then placed relative to the stack according to their top, right, bottom, and left properties.
Expanded must be placed only inside Column, Row or Flex widgets.
My code was working fine but now I'm unable to see the Profile page as it generates an error and I'm unable to identify, even though I tried to return a Container() at the end of buildProfileButton() but it did not solve the issue as I updated the code of that function later on.
class Profile extends StatefulWidget {
final String profileId;
Profile({this.profileId});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
final String currentUserId = currentUser?.id;
bool isLoading = false;
int postCount = 0;
bool isFollowing = false;
int followerCount = 0;
int followingCount = 0;
List<Post> posts = [];
#override
void initState() {
super.initState();
getProfilePosts();
getFollowers();
getFollowing();
checkIfFollowing();
}
checkIfFollowing() async {
DocumentSnapshot doc = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.get();
setState(() {
isFollowing = doc.exists;
});
}
getFollowers() async {
QuerySnapshot snapshot = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.getDocuments();
setState(() {
followerCount = snapshot.documents.length;
});
}
getFollowing() async {
QuerySnapshot snapshot = await followingRef
.document(widget.profileId)
.collection('userFollowing')
.getDocuments();
setState(() {
followingCount = snapshot.documents.length;
});
}
getProfilePosts() async {
setState(() {
isLoading = true;
});
QuerySnapshot snapshot = await postsRef
.document(widget.profileId)
.collection('userPosts')
.orderBy('rating', descending: true)
.getDocuments();
setState(() {
isLoading = false;
postCount = snapshot.documents.length;
posts = snapshot.documents.map((doc) => Post.fromDocument(doc)).toList();
});
}
Column buildCountColumn(String label, int count) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
count.toString(),
style: TextStyle(fontSize: 22.0, fontWeight: FontWeight.bold),
),
Container(
margin: EdgeInsets.only(top: 4.0),
child: Text(
label,
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
fontWeight: FontWeight.w400,
),
),
),
],
);
}
editProfile() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditProfile(currentUserId: currentUserId)));
}
Container buildButton({String text, Function function}) {
return Container(
padding: EdgeInsets.only(top: 2.0),
child: FlatButton(
onPressed: function,
child: Container(
width: 210.0,
height: 27.0,
child: Text(
text,
style: TextStyle(
color:
isFollowing ? Colors.white : Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
alignment: Alignment.center,
decoration: BoxDecoration(
color: isFollowing ? Theme.of(context).primaryColor : Colors.white,
border: Border.all(
color: Theme.of(context).primaryColor,
),
borderRadius: BorderRadius.circular(5.0),
),
),
),
);
}
buildProfileButton() {
bool isProfileOwner = currentUserId == widget.profileId;
if (isProfileOwner) {
return buildButton(
text: "Edit Profile",
function: editProfile,
);
} else if (isFollowing) {
return buildButton(
text: "Unfollow",
function: handleUnfollowUser,
);
} else if (!isFollowing) {
return buildButton(
text: "Follow",
function: handleFollowUser,
);
}
}
handleUnfollowUser() {
setState(() {
isFollowing = false;
});
followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
followingRef
.document(currentUserId)
.collection('userFollowing')
.document(widget.profileId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
activityFeedRef
.document(widget.profileId)
.collection('feedItems')
.document(currentUserId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
}
handleFollowUser() {
setState(() {
isFollowing = true;
});
followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.setData({});
followingRef
.document(currentUserId)
.collection('userFollowing')
.document(widget.profileId)
.setData({});
activityFeedRef
.document(widget.profileId)
.collection('feedItems')
.document(currentUserId)
.setData({
"type": "follow",
"ownerId": widget.profileId,
"username": currentUser.username,
"userId": currentUserId,
"userProfileImg": currentUser.photoUrl,
"timestamp": timestamp,
});
}
buildProfileHeader() {
return FutureBuilder(
future: usersRef.document(widget.profileId).get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
User user = User.fromDocument(snapshot.data);
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(
radius: 40.0,
backgroundColor: Colors.grey,
backgroundImage: CachedNetworkImageProvider(user.photoUrl),
),
Expanded(
flex: 1,
child: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildCountColumn("Videos", postCount),
buildCountColumn("Followers", followerCount),
buildCountColumn("Following", followingCount),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[buildProfileButton()],
),
],
),
),
],
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 12.0),
child: Text(
user.username,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 4.0),
child: Text(
user.displayName,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 2.0),
child: Text(
user.bio,
),
),
],
),
);
},
);
}
buildProfilePosts() {
if (isLoading) {
return circularProgress();
} else if (posts.isEmpty) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset('assets/images/no_content.svg', height: 260.0),
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Text(
"No Posts",
style: TextStyle(
color: Colors.redAccent,
fontSize: 40.0,
fontWeight: FontWeight.bold),
),
),
],
),
);
}
return Column(
children: posts,
);
}
buildTogglePostOrientation() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(Icons.videocam,
size: 30.0, color: Theme.of(context).primaryColor),
onPressed: null,
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: header(context, titleText: "PROFILE"),
body: ListView(
children: <Widget>[
buildProfileHeader(),
Divider(),
buildTogglePostOrientation(),
Divider(
height: 0.0,
),
buildProfilePosts(),
],
),
);
}
}
The debug console says that: A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 285 pos 10: 'data != null'
The relevant error-causing widget was
FutureBuilder
Instead of writing Text(description), write Text(description ?? '') so the Text widget will be empty if description is null.
When using the property of an object, instead of writing Text(user.bio) write Text(user?.bio ?? '') for the Text widget to get an empty string if user or user.bio is null.
You can Also make sure that the strings your using in the Text widget are never null.
Not related to the question but I see that you use a lot of functions to build your UI,
I suggest that you turn each of them to a separate widget to improve your app's performance. see this post to learn more.