ListView causes whitescreen below Appbar - flutter

I have a function that returns a Widget into my builder.
I want it to return a ListView, but everything below the Appbar just gets white with this piece of code in my return:
#override
Widget details(BuildContext context) {
var cell = (Widget widget) => Padding(
padding: EdgeInsets.all(5),
child: widget,
);
var locale = Localizations.localeOf(context);
return ListView(
children: <Widget>[
ListTile(title: Text("Test")),
],
);
}
The calling builder has this as body:
return Container(
//padding: EdgeInsets.all(32),
child: Column(
children: [
Container(
color: Color.fromRGBO(49, 161, 181, 0.4),
child:
Hero(
tag: collectible.heroTag,
child: Container(
width: double.infinity,
height: 250,
child: FadeInImage(
image: collectible.detailImage,
placeholder: collectible.icon,
fadeInDuration: Duration(milliseconds: 100),
fadeOutDuration: Duration(milliseconds: 100),
fadeInCurve: Curves.linear,
fadeOutCurve: Curves.linear,
// errorBuilder: (context, obj, satckTrace) =>
// Image.asset('images/bildfehlt.png'),
),
alignment: Alignment.center,
),
),
),
CheckboxListTile(
title: Text("Got it"),
controlAffinity: ListTileControlAffinity.leading,
value: collectible.isObtained(settings),
onChanged: (value) {
collectible.setObtained(settings, value);
},
),
collectible.details(context), // <-------- function
],
),
);
Did I implement sth wrong?
Any other widget, Container or Column for Example just work fine.
Error-Log:
https://pastebin.com/geSBXcB6

Related

Flutter add bottom margin to Stack

I am trying to extend Stack a little bit down to create room for "All caught up" text.
Here is my code;
return Stack(
children: [
buildListView(scrollController),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
Widget buildBackToTop(ScrollController scrollController, bool backtoTop) {
if (backtoTop) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton.extended(
onPressed: () {
scrollController.animateTo(0,
duration: const Duration(milliseconds: 200),
curve: Curves.linear);
},
label: const Text("Back to Top"),
),
),
);
} else {
return const SizedBox();
}
}
Widget buildBottomReached(bool isLastIndex) {
if (isLastIndex) {
return const Align(
alignment: Alignment.bottomCenter,
child: Text(
"All caught up 🎉",
style: TextStyle(
color: Colors.blue, fontWeight: FontWeight.bold, fontSize: 20.00),
),
);
} else {
return const SizedBox();
}
}
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}
When I do following,
return Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30),
child: buildListView(scrollController),
),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
This is desired but it adds whitespace to bottom all the time,
Is there a way to do this?
another valid solution for your case is to expand the Stack to the screen size, then align your widgets with the Align widget like this:
final mq = MediaQuery.of(context);
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: mq.size.height,
minHeight: mq.size.height,
maxWidth: mq.size.width,
minWidth: mq.size.width,
),
child: Stack(
fit: StackFit.expand,
children: [
buildListView(scrollController),
Align(
alignment: Alignment.bottomCenter,
child: buildBackToTop(scrollController, backtoTop),
),
buildBottomReached(isLastIndex),
],
),
);
Based on your UI. try Column widget instead of Stack.
return Column(
children: [
Expaneded(child: buildListView(scrollController)),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
If it needs overlay, use Stack by combining listView and Text with Column.
Wrap the widget with Positioned and add bottom.
return Stack(
children: [
.....
Positioned(
bottom: yourValue,
child:
First, wrap Stack with ListView widget
Then, move buildBottomReached helper as a sibling of the Stack widget
return ListView(//this
children: [
Stack(
children: [
buildListView(),
buildBackToTop(backtoTop),
//buildBottomReached(isLastIndex),//move this a sibling of the Stack
],
),
buildBottomReached(isLastIndex),//moved here
],
);
Then, on buildListView helper, set ListView.builder property shrinkWrap to true.
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
shrinkWrap: true,//this
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}

Vertical scrolling with horizontal scrolling lists render errors

Having difficulty with a Flutter layout which includes an appBar() at the top, a BottomNavigationWidget() at the bottom and content in the middle that is vertically scrollable but has horizontal list views as well. The problem is I continue to run into viewport errors that vary in their specificity, no matter what I attempt to correct or modify related to the SingleChildScrollView() that sits beneath the appBar().
Each horizontal row is built from a future that returns a list of images that comes from ContentList. Since I need to be able to make multiple requests for different images in each horizontal row, I call buildCategory("title", 0), buildCategory("new title", 1), buildCategory("another title", 2)and so on, as to pull down different images and display them with a unique title as illustrated in the image below.
I've constructed that layout like so below however you can't scroll vertically, only horizontally on each included buildCategory method despite being wrapped in a SingleChildScrollView and contained within a Column. If I deviate from this I get layout exceptions thrown.
I've included the full code I'm working with to better share/show.
Future<List<ContentDetails>> getContent(http.Client client, int filter) async {
var response = await client.get(
Uri.parse(baseUrl + '/imageendpoint/$filter'));
if (response.statusCode == 200) {
compute(parseContentDetails, response.body);
}
}
List<ContentDetails> parseContentDetails(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed
.map<ContentDetails>((json) => ContentDetails.fromJson(json))
.toList();
}
class ContentList extends StatefulWidget {
const ContentList({Key? key, required this.photos}) : super(key: key);
final List<ContentDetails> photos;
#override
State<ContentList> createState() => _ContentListState();
}
class _ContentListState extends State<ContentList> {
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: widget.photos.length,
itemBuilder: (context, index) {
return Stack(
alignment: Alignment.topCenter,
children: <Widget>[
InkWell(
onTap: () {},
child: Container(
height: 150.0,
width: 150.0,
child: Container(
image: DecorationImage(
fit: BoxFit.cover,
alignment: FractionalOffset.center,
image: widget.photos[index].image,
),
),
child: Container(
child: Padding(
padding: const EdgeInsets.only(bottom: 0),
child: Text(widget.photos[index].name)),
),
),
),
),
),
],
);
},
);
}
}
Widget appBar() {
return AppBar(
title: const Text("Welcome"),
centerTitle: true,
backgroundColor: Colors.transparent
);
}
Widget horizontalContent(int filter) {
return FutureBuilder<List<ItemDetails>>(
future: getContent(http.Client(), filter),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('Error.'),
);
} else if (snapshot.hasData) {
return ContentList(photos: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
);
}
Widget buildCategory(String title, int category) {
return Flexible(
child: ListView(
shrinkWrap: true,
children: [
Padding(
padding: const EdgeInsets.all(5.0),
child:
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
TitleWidget(
titleText: title,
titleAlign: TextAlign.right),
SmallButton(
buttonText: "Details",
onPressed: () => {},
)
]),
),
SizedBox(height: 200, child: horizontalContent(filter))
],
),
);
}
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
bottomNavigationBar: BottomNavigationWidget(),
body: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color.fromRGBO(0, 85, 85, 85),
Color.fromRGBO(0, 66, 66, 66),
Color.fromRGBO(0, 0, 0, 0),
],
stops: [0.0, 0.3],
),
),
child:
Image.asset("images/background.png", fit: BoxFit.cover)),
appBar(),
SingleChildScrollView(
child: Column(mainAxisSize: MainAxisSize.min, children: [
buildCategory("title", 0),
buildCategory("title", 1),
buildCategory("title", 2),
buildCategory("title", 3),
buildCategory("title", 4),
buildCategory("title", 5),
buildCategory("title", 6),
])),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[BottomNavigationWidget()],
),
],
),
);
}
}
On your Scaffold use appBar and
AppBar appBar() {
return AppBar(
title: const Text("Welcome"),
centerTitle: true,
backgroundColor: Colors.transparent);
}
return Scaffold(
appBar: appBar(),
// bottomNavigationBar: ,
body: ListView.builder( // top level listView
itemCount: 44,
itemBuilder: (context, index) {
return Container(
height: 200, // must provide based on your preference
child: Column(
children: [
Row(
children: [
Text("header $index"),
],
),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 33,
itemBuilder: (context, index) => Container(
width: 200,
height: 100,
child: Text("hrIem"),
),
),
),
],
),
);
},
),
);
Try this
Scaffold(
extendBodyBehindAppBar: true,
appBar: appBar(),
bottomNavigationBar: BottomNavigationWidget(),
body: ListView(
children: [
SizedBox(
height: 300, // give your height
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
mainAxisSize: MainAxisSize.min, children: [
buildCategory("title", 0),
buildCategory("title", 1),
buildCategory("title", 2),
buildCategory("title", 3),
buildCategory("title", 4),
buildCategory("title", 5),
buildCategory("title", 6),
]
)
),
),
SizedBox(
height: 300, // give your height
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
mainAxisSize: MainAxisSize.min, children: [
buildCategory("title", 0),
buildCategory("title", 1),
buildCategory("title", 2),
buildCategory("title", 3),
buildCategory("title", 4),
buildCategory("title", 5),
buildCategory("title", 6),
]
)
),
)
]
),
)

How to change position of Container inside Stack?

Im trying to displaying a button inside my stack but it not getting the correct position. The button is the reply Button . I added a foot how it looks at the moment you can check it what I want is displaying it on the right side of the window at the bottom with a bit of spacing between bottom and the button.
Hope anyone can help. if you need more information please leave a comment .
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
try {
return Scaffold(
body: StreamBuilder(
stream: mystreamofallvideos,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState != ConnectionState.waiting) {
return PageView.builder(
itemCount: snapshot.data.docs.length,
controller:
PageController(initialPage: 0, viewportFraction: 1),
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
DocumentSnapshot videos = snapshot.data.docs[index];
return Stack(children: [
Videoplayeritem(widget.videoid),
Column(children: [
Align(
alignment: Alignment.bottomLeft,
child: Container(
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
size: 35,
),
onPressed: () {
Navigator.of(context).pop();
}),
SizedBox(
width: 190,
),
],
),
),
),
Container(
color: Colors.red,
width: 210,
height: 94,
//color: Colors.blue.withOpacity(0.5),
child: InkWell(
onTap: () => sharevideo(
widget.videoid, videos.data()['id']),
child: Icon(Icons.reply,
size: 55, color: Colors.white),
),
),
]),
//starssonthe right
]);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
);
} catch (e) {
e.toString();
}
}
}
This is how it looks
enter image description here
Wrap it in an align and add a padding to the bottom:
Align(
alignment: Alignment.bottomRight,
child: Container(
height: 40,
padding: const EdgeInsets.only(bottom: 16),
child: OutlinedButton(
onPressed: () {},
child: Text('mybutton'),
),
)
you can wrap your container with either Positioned or Align widgets
like :
Positioned(
top: 0.0,
left: 0.0,
child: Icon(Icons.message,
size: 128.0, color: Colors.greenAccent[400]), //Icon
),

Translate other elements on DraggableScrollableSheet top-bottom movement

Hi I have to translate two of my widgets based on the DraggableScrollableSheet drag position (you can think this bottom sheet as in GMaps). The widgets I have to move/animates are:
Text - It needs to translate & scale back-and-forth and in-out respectively following an arc path simultaneously. (See expected video)
Row - It needs to translate a bit and then out. Again back-and-forth.
Trails -
Text widget scaling in-out properly but translating in some weird way. (See actual video)
Row widget is fading in-out fine, but having a hard time translating it.
Expected Vid -
https://drive.google.com/file/d/1wg3q8KJc6zMe3b6mw-LgPN62FxK4dMMj/view?usp=sharing
actual vid -
https://drive.google.com/file/d/1umjDVj6PXqiatF6JVt8EeKTCxU2LyM7E/view?usp=sharing
Code -
final Duration _animationDuration = const Duration(milliseconds: 300);
bool _isNavShown = true;
double yValue = -35.0;
void _applyEffectsOnDrag(double factor) {
print(factor);
if (factor > 0.7) {
_isNavShown = false;
} else {
_isNavShown = true;
}
}
Widget _getNavigationButtons(BuildContext ctx, bool isHidden) {
return Padding(
padding: verticalAndHorizontailPadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
...[1, 2, 3]
.map(
(e) => Container(
decoration: CircleStyles.navButton,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding: padding
decoration: decoration,
child: Icon(Icons.verified_user),
),
SizedBox(height: AppMediaQuery(ctx).appHeight(2)),
Text('block heading')
],
),
),
)
.toList()
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(gradient: Variables.circleGradient),
child: Stack(
children: [
Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: AppMediaQuery(context).appHorizontalPadding(4),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
// TODO: Goto home screen
},
child: Container(
alignment: Alignment.center,
width: 32,
height: 32,
decoration: backButtonStyle,
child: const Icon(
Icons.chevron_left,
),
),
),
IconButton(icon: const Icon(Icons.more_horiz), onPressed: null),
],
),
),
TweenAnimationBuilder(
duration: _animationDuration,
curve: Curves.easeInOut,
tween: Tween<double>(begin: 0, end: !_isNavShown ? yValue : 0),
child: Padding(
padding: somePadding,
child: const Align(
alignment: Alignment.centerLeft,
child: const Text('Circles'),
),
),
builder: (_, double dy, Widget ch) {
return Transform.scale(
scale: _isNavShown ? 1 : 0.8,
child: Transform.translate(
offset: Offset(0, dy),
child: ch,
),
);
},
),
AnimatedOpacity(
duration: _animationDuration,
opacity: _isNavShown ? 1 : 0,
child: _getNavigationButtons(context, true),
),
],
),
NotificationListener<DraggableScrollableNotification>(
onNotification: (obj) {
setState(() {
return _applyEffectsOnDrag(obj.extent);
});
},
child: DraggableScrollableSheet(
initialChildSize: 0.6,
minChildSize: 0.6,
maxChildSize: 0.9,
builder: (context, ctrl) {
return Container(
decoration: CircleStyles.sheetBase,
child: ConversationList(ctrl),
);
},
),
),
],
),
),
);
}

render slivergrid using bloc in flutter

Here is the case :-
i have a Bloc named XYZBloc which loads data from network. i need to render these lists into sliverGrid.
the same list goes pretty well with sliverList.
Store.dart
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _xyzBloc,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Container(
width: MediaQuery.of(context).copyWith().size.width,
height: MediaQuery.of(context).copyWith().size.height,
child: BlocBuilder<XyzBloc, XyzState>(
bloc: _xyzBloc,
builder: (context, state) {
if (state is XYZLoadingState) {
return buildLoading();
} else if (state is XYZErrorState) {
return buildErrorUi(state.message);
} else if (state is XYZLoadedState) {
return _buildPageView(state.lists, context);
} else {
return Container();
}
}),
),
),
);
}
_buildPageView(List<XYZModel> lists, BuildContext context) {
return SliverGrid(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return Container(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.grey, height: 130.0, width: double.infinity),
Text(lists[index].name)
],
),
);
}, childCount: lists.length),
);
}
code to load sliverGrid data :-
Home.dart
#override
Widget build(BuildContext context) {
double cardWidth = MediaQuery.of(context).size.width / 3.3;
double cardHeight = MediaQuery.of(context).size.height / 3.6;
return Container(
color: AppTheme.nearlyWhite,
child: Scaffold(
backgroundColor: Colors.transparent,
body: Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).padding.top,
),
getAppBarUI(),
Expanded(
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
Padding(
padding: EdgeInsets.all(15),
child: Container(
width: MediaQuery.of(context).size.width,
height: 150,
child: BannerItems(),
),
),
])),
SliverList(
delegate: SliverChildListDelegate(
[
Padding(
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: Container(
decoration: BoxDecoration(color: Colors.transparent),
height: 100,
child: Category(),
),
),
],
),
),
Stores(),
],
)),
],
),
),
);
}
i have tried all possible way to debug but my noob sense couldn't help me to understand how this sliverGrid works with network data.
any suggestion, reference will be highly appreciated.