Flutter TikTokStyleFullPageScroller() not working on empty (non content) screen - flutter

I am new to Flutter and trying to add slide functions to videos. It seems to be working as expected but only if slide by tapping on content area. In other words if tapped on video to slide it doesn't work.
Package:
tiktoklikescroller: ^0.1.1
import 'package:tiktoklikescroller/tiktoklikescroller.dart';
Here is my code:
#override
Widget build(BuildContext context) {
final List<Color> colors = <Color>[Colors.red, Colors.blue, Colors.yellow];
return Expanded(
child: TikTokStyleFullPageScroller(
contentSize: colors.length,
swipeThreshold: 0.2,
swipeVelocityThreshold: 2000,
animationDuration: const Duration(milliseconds: 300),
builder: (BuildContext context, int index) {
return Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
VideoDescription(),
ActionToolbar(),
],
);
},
),
);
}
Video Description
class VideoDescription extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Expanded(
child: Align(
alignment: Alignment.bottomLeft,
child: Container(
height: 70.0,
padding: EdgeInsets.only(left: 20.0),
margin: EdgeInsets.only(bottom: 160.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Title', style: TextStyle(fontWeight: FontWeight.bold),),
],
),
),
),
);
}
}
Action Toolbar
#override
Widget build(BuildContext context) {
return Container(
width: 100.0,
margin: EdgeInsets.only(bottom: 25.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_getMusicPlayerAction(),
],
),
);
}
Please help.

I wrapped VideoDescription() and ActionToolbar() inside a container and gave it a transparent color.
#override
Widget build(BuildContext context) {
final List<Color> colors = <Color>[Colors.red,
Colors.blue, Colors.yellow];
return Expanded(
child: TikTokStyleFullPageScroller(
contentSize: colors.length,
swipeThreshold: 0.2,
swipeVelocityThreshold: 2000,
animationDuration: const Duration(milliseconds: 300),
builder: (BuildContext context, int index) {
return Container(
color: Colors.transparent,
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
VideoDescription(),
ActionToolbar(),
],
),
);
},
),
);
}

Related

Error show during compile time: The method '[]' was called on null. Receiver: null

I am getting an error with a single listing page or detailed page.
It shows the method [] was called on null.
But is as defined some itemData in main dart file it also showa same error. please help me to solve this error.
this is my DetailPage.dart file
import 'package:flutter/material.dart';
import 'package:uidesign/custom/BorderIcon.dart';
import 'package:uidesign/custom/OptionButton.dart';
import 'package:uidesign/utils/constants.dart';
import 'package:uidesign/utils/custom_functions.dart';
import 'package:uidesign/utils/widget_functions.dart';
class DetailPage extends StatelessWidget {
final dynamic itemData;
const DetailPage({super.key, #required this.itemData});
//DetailPage({Key? key,#required this.itemData}) : super(key: key);
#override
Widget build(BuildContext context){
final Size size = MediaQuery.of(context).size;
final ThemeData themeData = Theme.of(context);
final double padding = 25;
final sidePadding = EdgeInsets.symmetric(horizontal: padding);
return SafeArea(
child: Scaffold(
backgroundColor: COLOR_WHITE,
body: Container(
width: size.width,
height: size.height,
child: Stack(
children: [
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
Image.asset(itemData["image"]),
Positioned(
width: size.width,
top: padding,
child: Padding(
padding: sidePadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: (){
Navigator.pop(context);
},
child: BorderIcon(
padding: new EdgeInsets.all(0.0),
height: 50,
width: 50,
child: Icon(
Icons.keyboard_backspace, color:COLOR_BLACK,
),
),
),
BorderIcon(
padding: new EdgeInsets.all(0.0),
width: 50,
height: 50,
child: Icon(Icons.favorite_border, color: COLOR_BLACK),
),
],
),
),
),
],
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("${formatCurrency(itemData["amount"])}",style: themeData.textTheme.headline1,),
addVerticalSpace(5),
Text("\$${itemData["address"]}",style: themeData.textTheme.subtitle2,),
]
),
BorderIcon(
width: 0,
height: 0,
child: Text("20 Hours ago",style: themeData.textTheme.headline5,),padding: const EdgeInsets.symmetric(vertical: 15,horizontal: 15),
)
],
),
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Text("House Information",style: themeData.textTheme.headline4,),
),
addVerticalSpace(padding),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
child: Row(
children: [
InformationTile(content: "${itemData["area"]}",name: "Square Foot",),
InformationTile(content: "${itemData["bedrooms"]}",name: "Bedrooms",),
InformationTile(content: "${itemData["bathrooms"]}",name: "Bathrooms",),
InformationTile(content: "${itemData["garage"]}",name: "Garage",)
],
),
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Text(
itemData["description"],
textAlign: TextAlign.justify,
style: themeData.textTheme.bodyText2,
),
),
addVerticalSpace(200),
],
),
),
Positioned(
bottom: 20,
width: size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OptionButton(text: "Message",icon: Icons.message,width: size.width*0.35,),
addHorizontalSpace(10),
OptionButton(text: "Call",icon: Icons.call,width: size.width*0.35,),
],
),
),
],
),
),
),
);
}
}
class InformationTile extends StatelessWidget{
final String content;
final String name;
const InformationTile({super.key, required this.content, required this.name});
#override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final double tileSize = size.width*0.20;
return Container(
margin: const EdgeInsets.only(left: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BorderIcon(
padding: new EdgeInsets.all(0.0),
width: tileSize,
height: tileSize,
child: Text(content,style: themeData.textTheme.headline3,)),
addVerticalSpace(15),
Text(name,style: themeData.textTheme.headline6,)
],
),
);
}
}
this is my Sample_data.dart file
in this file i add some sample data in json format
and this is how i define my DetailPage file in main.dart file
import 'package:flutter/material.dart';
import 'package:uidesign/screens/LandingPage.dart';
import 'package:uidesign/screens/DetailPage.dart';
import 'package:uidesign/utils/constants.dart';
import 'dart:ui';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
double screenWidth = window.physicalSize.width;
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Design 1',
theme: ThemeData(primaryColor: COLOR_WHITE, accentColor: COLOR_DARK_BLUE, textTheme: screenWidth < 500 ? TEXT_THEME_SMALL : TEXT_THEME_DEFAULT, fontFamily: "Montserrat"),
//home: LandingPage(),
//home: DetailPage(itemData: 1),
home: const DetailPage(),
);
}
}
error in terminal: the line i select on terminal is the error
Please help me out how it get the data with the key
Pass your RE_DATA list here in MainScreen
home: DetailPage(itemData: RE_DATA)
And Change List<dynamic> itemData to List<Map<String,dynamic>> itemData in DetailPage.
You are getting list so access itemData like this itemData[index]['image']
If possible use model for your RE_DATA instead of passing List of Maps.

Flutter set widget position exactly center of the screen

I want to put a container widget in the middle of the device screen. However, since I used the SizedBox() and SvgPicture.asset() widgets before that, the container does not come right in the middle of the device. How can I do this?
This is my code:
class CenterWidget extends StatefulWidget {
const CenterWidget({Key? key}) : super(key: key);
#override
_CenterWidgetState createState() => _CenterWidgetState();
}
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
Expanded(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}
Use a top center aligned stack, and put the widget you want to be centered within a Positioned.fill widget. You can put the spacer and logo in their own column to keep them arranged vertically:
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Stack(
alignment: Alignment.topCenter,
children: [
Column(
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
],
),
Positioned.fill(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}

How to add rounded corners to BottomAppBar with CircularNotchedRectangle in Flutter

I want to create BottomAppBar with rounded corners, circular notched rectangle and material shadow.
The problem is that when I add rounded corners to BottomAppBar by wrapping it with ClipRRect widget I lose material shadow.
BottomAppBar without rounded corners, but with Material shadow. Please ignore wrong aligned notch.
BottomAppBar wrapped in ClipRRect widget, but without shadow. Again please ignore wrong aligned notch:
How to achieve rounded corners with notch and material shadow?
Full code:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
extendBody: true,
body: Container(
color: Colors.amber,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Transform.translate(
offset: Offset(0, -10),
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
elevation: 2.0,
),
),
bottomNavigationBar: BottomNavigationView(),
),
);
}
}
class BottomNavigationView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -10),
child: Container(
margin: EdgeInsets.only(left: 20, right: 20),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30),
),
child: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
),
_buildMiddleTabItem(),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
)
],
),
),
),
),
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: 60,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 24),
Text(''),
],
),
),
);
}
}
You can create your own ShapeBorder.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
extendBody: true,
body: Container(
color: Colors.amber,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Transform.translate(
offset: Offset(0, -10),
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
elevation: 2.0,
),
),
bottomNavigationBar: BottomNavigationView(),
),
);
}
}
class BottomNavigationView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -10),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
padding: EdgeInsets.symmetric(horizontal: 20),
decoration: ShapeDecoration(
color: Colors.white,
shape: MyBorderShape(),
shadows: [
BoxShadow(
color: Colors.black38, blurRadius: 8.0, offset: Offset(1, 1)),
],
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
),
_buildMiddleTabItem(),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessibility_new),
],
)
],
),
),
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: 60,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 24),
Text(''),
],
),
),
);
}
}
class MyBorderShape extends ShapeBorder {
MyBorderShape();
#override
EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
#override
Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;
double holeSize = 70;
#override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
print(rect.height);
return Path.combine(
PathOperation.difference,
Path()
..addRRect(
RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2)))
..close(),
Path()
..addOval(Rect.fromCenter(
center: rect.center.translate(0, -rect.height / 2),
height: holeSize,
width: holeSize))
..close(),
);
}
#override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
#override
ShapeBorder scale(double t) => this;
}

Can't find correct layout option for how to use ListView in a custom Widget

I am trying to extract re-use a simple widget that is then referenced in parent widget. The custom widget simply uses a row to layout a textField and a button, and below this I Want to have a listview showing items. I then embed in the customwidget in parent, but it continually throws Error. I have not figured out how to get the custom widget working where I can use ListView or column layout inside. Below is the 2 simplified widgets that demo the issue.
Here is the parent widget, which is where I call the custom widget PlayListControl()
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Playlists'),
),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.all(20),
child: Text('Test'),
),
PlayListControl(),
],
),
),
drawer: SideDrawer(),
);
}
}
And here is the playlistcontrol widget.
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 200,
child: TextField(),
),
ButtonTheme(
minWidth: 30,
child: RaisedButton(
textColor: Colors.white,
child: Text('add'),
onPressed: () {},
)),
],
),
),
Expanded(
child: ListView(
children: <Widget>[
Text('Widget 1'),
Text('Widget 2'),
],
),
)
],
),
);
}
}
No matter what I try, it always complains about layout issue related to height. I would have thought wrapping the ListView in Expanded would solve the issue, but it doesn't. Only if I use a container and specify height do I not get the errors, but I want to use whatever available space there is.
How can I get this playlistcontrol() widget to properly render inside a parent control?
you forgot to wrap the first container of PlayListControl in Expanded widget..
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: Text('My Playlists'),
),
body: Container(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.all(20),
child: Text('Test'),
),
PlayListControl(),
],
),
),
));
}
}
class PlayListControl extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Expanded(
child: Container(
margin: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 200,
child: TextField(),
),
ButtonTheme(
minWidth: 30,
child: RaisedButton(
textColor: Colors.white,
child: Text('add'),
onPressed: () {},
)),
],
),
),
Expanded(
child: ListView(
children: <Widget>[
Text('Widget 1'),
Text('Widget 2'),
],
),
)
],
),
),
);
}
}

Unable to get page scroll even adding the content inside a SingleChildScrollView or the ListView

I'm new to Flutter.
What I'm trying to achieve is a page that has a transparent AppBar with a widget behind it. That's how it looks now:
The problem is that, I can't make the page scroll when the content is bigger then the viewport height, even adding a SingleChildScrollView or adding the content inside a ListView, it just don't scrolls.
This is the page:
import 'package:cinemax_app/src/blocs/movie_bloc.dart';
import 'package:cinemax_app/src/components/movie/movie_header.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({ this.movieId });
#override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
#override
void initState() {
super.initState();
movieBloc.fetchMovie(widget.movieId);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: movieBloc.movie,
builder: (context, snapshot) {
final _movie = snapshot.data as MovieModel;
return Scaffold(
body: SafeArea(
child: snapshot.hasData ?
Stack(
children: <Widget>[
ListView(
shrinkWrap: true,
children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding: EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:', style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]
),
AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: Text('Partilhar'),
value: 'share'
),
PopupMenuItem(
child: Text('Comprar bilhete'),
value: 'share',
enabled: false,
),
];
},
onSelected: (selectedPopupValue) {
switch (selectedPopupValue) {
case 'share': {
final movieSlug = _movie.slug;
final movieAddress = 'https://cinemax.co.ao/movie/$movieSlug';
Share.share(movieAddress);
}
}
},
)
],
),
]
) :
Center(
child: CircularProgressIndicator(),
)
),
);
}
);
}
}
The MovieHeader widget:
import 'dart:ui' as prefix0;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'movie_cover.dart';
class MovieHeader extends StatelessWidget {
const MovieHeader({Key key, #required MovieModel movie}) : _movie = movie, super(key: key);
final MovieModel _movie;
#override
Widget build(BuildContext context) {
return Container(
height: 250,
color: Colors.black,
child: Column(
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
new MovieBanner(movie: _movie),
Positioned(
bottom: -15.0,
left: 15.0,
right: 15.0,
child: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
width: 125.0,
child: MovieCover(imageUrl: _movie.coverUrl)
),
Padding(padding: EdgeInsets.only(right: 15.0),),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text(
_movie.name,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
)
),
),
],
),
Padding(padding: EdgeInsets.only(bottom: 10.0),),
Text(
_movie.genresList,
style: TextStyle(
fontSize: 10.0,
color: Colors.white.withOpacity(0.6)
),
),
Padding(padding: EdgeInsets.only(bottom: 35.0),)
],
),
)
],
)
),
)
],
)
),
],
),
);
}
}
class MovieBanner extends StatelessWidget {
const MovieBanner({
Key key,
#required MovieModel movie,
}) : _movie = movie, super(key: key);
final MovieModel _movie;
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
Opacity(
child: CachedNetworkImage(
imageUrl: _movie.bannerUrl,
fit: BoxFit.cover,
),
opacity: 0.5,
),
Positioned(
child: ClipRect(
child: BackdropFilter(
child: Container(color: Colors.black.withOpacity(0)),
filter: prefix0.ImageFilter.blur(sigmaX: 5, sigmaY: 5),
),
),
)
],
);
}
}
Why is it happening? What I'm doing wrong?
An Example of Scrolling ListView using ListView Builder
class ScrollingList extends StatelessWidget{
List<String> snapshot= ["A","B","C","D","E","F","G"]
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder( //<----------- Using ListViewBuilder
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Card( //<--------- Using Card as per my requirement as a wrapper on List tile, you can use any other UI Element
child: ListTile( // populating list tile with tap functionality
title: Text(
'${snapshot.data[index]}',
maxLines: 1,
),
onTap: () {
print('TAPPED = ${snapshot.data[index]}') //<---- do anything on item clicked eg: open a new page or option etc.
}),
);
},
);
)
}
for any reference of single child scroll view here is a link