Text is placed on the screen but it scroll - android

android studio 3.6
I need to scroll text only if text does not fit the screen. So if text is placed on the screen it MUST NOT scroll.
snippet:
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.orange,
body: SafeArea(
child: SingleChildScrollView(
child: new Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new Column(
children: [
new Text("column_1", style: TextStyle(backgroundColor: Colors.yellow)),
new Text("column_2", style: TextStyle(backgroundColor: Colors.blue)),
new Text("column_3", style: TextStyle(backgroundColor: Colors.black12))])))));
}
}
result
but I can scroll. Why?

It is scrolling as your column sits inside a singleChildScrollView() which enables scrolling by default.
As our container was using a MediaQuery to set its height, the singleChildScrollView() has no vertical space to expand into and thus resulted in the scrolling behaviour.
Instead we should wrap our singleChildScrollView() inside a container and then perform the MediaQuery on that container instead.
Please see the below code:
return new Scaffold(
backgroundColor: Colors.orange,
body: SafeArea(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: SingleChildScrollView(
child: new Container(
child: new Column(
children: [
new Text(
"column_1",
style: TextStyle(backgroundColor: Colors.yellow),
),
new Text(
"column_2",
style: TextStyle(backgroundColor: Colors.blue),
),
new Text(
"column_3",
style: TextStyle(backgroundColor: Colors.black12),
),
],
),
),
),
),
),
);

Here my solution
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: new Column(children: [
new Container(height: 64.0, color: Colors.blue),
new Container(
height: Constants.CARD_VIEW_HEIGHT, color: Colors.yellow),
new Container(height: 356.0, color: Colors.red)
]))));
}
}

ListView is the simplest answer I think;
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.orange,
body: SafeArea(
child: new Container(
color: Colors.red,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new ListView(
shrinkWrap: true,
children: [
Center(child: new Text("column_1", style: TextStyle(backgroundColor: Colors.yellow))),
Center(child: new Text("column_2", style: TextStyle(backgroundColor: Colors.blue))),
Center(child: new Text("column_3", style: TextStyle(backgroundColor: Colors.black12)))]))));
}
}

Maybe use height and width on the ScrollView itself, rather than Column. The Column is taking more space on screen, causing it to scroll.

Related

How to have a ListView without scrolling the parent column view in flutter?

Please look at this image Home Page
Now when I scroll the ListView it becomes like this -
Home Page
Now I know the reason why this is happening, it is because I used ListView as a parent to this entire view and added ListView.builder() and other widgets as its child.
What I want is to scroll the ListView.builder() without scrolling the entire page.
For this I first tried to use Column as parent but that ended up giving the overflow pixels error.
And then I set the physics: const NeverScrollableScrollPhysics() inside the parent ListView but after that it made my ListView.builder() to show all of its list items.
Here is my Code for Home Screen
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
Recent()
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
); }
Recent List Code
class RecentItems extends StatefulWidget {
final List<Transaction> transactions;
RecentItems({required this.transactions});
#override
State<RecentItems> createState() => _RecentItemsState();
}
class _RecentItemsState extends State<RecentItems> {
#override
Widget build(BuildContext context) {
return SizedBox(
height: 450,
child: Expanded(child: ListView.builder(
itemBuilder: (context, index) {
final item = widget.transactions[index].toString();
return Dismissible(
direction: DismissDirection.endToStart,
key: UniqueKey(),
onDismissed: (direction) {
setState(() {
widget.transactions.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Transaction Deleted')));
},
background: Container(
color: Colors.red,
alignment: AlignmentDirectional.centerEnd,
child: const Padding(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 15.0, 0.0),
child: Icon(
EvaIcons.trash2,
color: Colors.white,
),
),
),
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: ListTile(
leading: CircleAvatar(
radius: 30,
foregroundImage: widget.transactions[index].Image,
backgroundColor: primaryColor,
),
title: Text(
widget.transactions[index].title,
style: const TextStyle(color: secondaryColor),
),
subtitle: Text(
DateFormat.yMMMd().format(widget.transactions[index].date),
),
trailing: Text(
'\$${widget.transactions[index].amount}',
style: const TextStyle(color: secondaryColor),
),
),
),
);
},
itemCount: widget.transactions.length,
),)
);
}
}
Recent Widget -
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Recent Transactions',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: secondaryColor),
),
const SizedBox(height: 5),
RecentItems(transactions: _userTransactions),
],
),
)
The entire screen scrolls because Recent() is included in the same ListView as header() and balanceCard().
Try something like this:
Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
],
),
),
// Recent items removed from ListView
Recent(),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
)
I hope this helps.
By simplifying your code, this is an example of a layout where you have a single Column in the Scaffold. The Column contains some sized, unsized and aligned children.
One child, Recent is a ListView, without explicit height, but wrapped into an Expanded widget. This way it will occupy all the remaining area left by the other children, and it will be scrollable.
(You will run into trouble with this if the children without Recent occupy all the available area.)
Please have a look at this code, you can copy-paste it into a DartPad fiddle:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => Scaffold(
body: Column(
children: [
const Text('header()'),
const SizedBox(height: 36),
const Text('BalanceCard()'),
const SizedBox(height: 36),
Expanded(child: Recent()),
const Align(
alignment: Alignment.bottomCenter,
child: Text('bottomNavigationBar()'),
),
],
),
);
}
class Recent extends StatelessWidget {
#override
Widget build(BuildContext context) => ListView.builder(
itemCount: 100, itemBuilder: (context, index) => Text('Item $index'));
}

The relevant error-causing widget was Container lib\screens\home_screen.dart:18

I am unable to put horizontal list view after row.
I want something like this..
here is my code for it ( i have that search bar widget in saperate file thats working fine,i dont have category itmes svgs yet so using text as child only)
here is my code:
class CategoriesListView extends StatelessWidget {
CategoriesListView({Key? key}) : super(key: key);
final List<String> _categories = ['Fruits', 'Vegetables', 'Fishes', 'Dairy'];
Widget categoryWidget(BuildContext context, String title) {
return Expanded(
child: Container(
height: 50,
width: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).primaryColor,
border: Border.all(color: Theme.of(context).primaryColor)),
child: Text(title)),
);
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
margin: margin,
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
'Category',
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
fontWeight: FontWeight.w600),
),
),
TextButton(
onPressed: null,
child: Text(
'See all',
style: TextStyle(color: Theme.of(context).primaryColor),
)),
],
),
ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children:
_categories.map((e) => categoryWidget(context, e)).toList())
]),
);
}
}
but ended up getting :
════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: _RenderColoredBox#f3a92
'package:flutter/src/rendering/box.dart':
package:flutter/…/rendering/box.dart:1
Failed assertion: line 1927 pos 12: 'hasSize'
The relevant error-causing widget was
Container
lib\screens\home_screen.dart:18
If any other information need, i am ready to provide.
Here is your working code
class CategoriesListView extends StatelessWidget {
CategoriesListView({Key? key}) : super(key: key);
final List<String> _categories = ['Fruits', 'Vegetables', 'Fishes', 'Dairy'];
Widget categoryWidget(BuildContext context, String title) {
return Container(
height: 50,
width: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).primaryColor,
border: Border.all(color: Theme.of(context).primaryColor)),
child: Text(title),);
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
margin: margin,
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
'Category',
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
fontWeight: FontWeight.w600),
),
),
TextButton(
onPressed: null,
child: Text(
'See all',
style: TextStyle(color: Theme.of(context).primaryColor),
)),
],
),
Expanded(
child: ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children:
_categories.map((e) => categoryWidget(context, e)).toList()))
]),
);
}
}
Console throw hasSize error because of your ListView is not wrap with Container. In Flutter , ListView don't have their own height and width. So always wrap your ListView with Container and it's height.
Do one thing:
Remove Expanded widget from Container.
Wrap your ListView with Container.
Container(
height: 200, // height should be as per your desire
child: ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: _categories.map((e)=>categoryWidget(context,e)).toList(),
),
),

How to slide pages under appbar flutter

I've been trying so hard to build page view system for quotes app. I want the page to flow full screen from top to bottom and bottom to top scrollable/swipe able to navigate between different quotes each time
like this. The scroll will bring new page each time its not casual scroll. I haven't found any guide regarding this on internet so far.
I don't know about how to build it, nothing is popping in my mind for days now. I've tried pageview with gesture detector for swiping up and down, it doesn't works as desired and appbar is static too and the bottom containers as well I don't want this. What I want is the page/screen to flow under the appbar or even a button on top right corner and under 2 buttons on the bottom.
Create a column of Containers where each Container's height and width equals the height and width of the screen. You can do that by using:
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
Also, make sure to wrap your code with a SingleChildScrollView widget to scroll vertically.
Here's the code:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text('Quote number one')),
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(
icon: Icon(Icons.favorite), onPressed: () {})
],
),
)
],
),
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
Text('Quote number two'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(icon: Icon(Icons.favorite), onPressed: () {})
],
)
],
),
)
],
),
),
),
);
}
}
You can use PageView to get this type of view
Drive Video link
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
PageView pageView;
List<String> quotes = [
'#Quote 1\n\n“I\'m selfish, impatient and a little insecure. I make mistakes, I am out of control and at times hard to handle. But if you can\'t handle me at my worst, then you sure as hell don\'t deserve me at my best.” ',
'#Qoute 2\n\nSo many books, so little time.',
'#Quote 3\n\n A room without books is like a body without a soul'
];
#override
void initState() {
super.initState();
pageController = PageController();
final _quotes = List.generate(quotes.length, (index) => quoteWidget(index));
pageView = PageView(
children: _quotes,
controller: pageController,
scrollDirection: Axis.vertical,
);
}
Widget quoteWidget(int index) {
return Scaffold(
backgroundColor: Colors.black,
body: Column(
children: [
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Text(
quotes[index],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w300,
color: Colors.white,
),
),
),
),
),
Expanded(
flex: 1,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.share),
),
const SizedBox(width: 20),
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.favorite_border),
),
],
),
),
Expanded(child: Container())
],
),
);
}
#override
void dispose() {
pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
brightness: Brightness.dark,
title: Text(widget.title),
),
body: SafeArea(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
pageView,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
RaisedButton.icon(
icon: Icon(Icons.menu_book),
label: Text('General'),
onPressed: () {},
),
const Spacer(),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.color_lens),
),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.person),
),
],
),
)
],
),
),
);
}
}

How to set a BackdropFilter using dynamic-sized widgets in Flutter

I have a column: header with text, body with image, footer with text, all widgets have transparent backgrounds.
I want to set the background using a blur of the main image but I keep reaching dead ends.
In some situations this would be straight forward but in my scenario the image could be of any size and aspect ratio, and I need the effect to be wrapped with the column.
Here are my two failed attempts:
Method 1
I have a Stack with the image as the first item, then a BackdropFilter with ImageFilter blur, then my Column.
This works but the Image bleeds out from under the Column because of the image size (which can be any size).
I want to constrain it to the height of my Column.
return Container(
child: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
Positioned.fill(child: Image.network(_imgUrl)),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)),
)),
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
// https://stackoverflow.com/a/41846093/3429021
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Header(),
BodyPhoto(),
Footer()
],
),
),
],
),
Method 2
Putting the column in a Container with a DecorationImage, which sizes the image perfectly, but I have no way of applying the blur effect.
(_streamItem is my Column wrapped in a container)
body: Container(child: _streamItem,
decoration: new BoxDecoration(image: DecorationImage(
image: NetworkImage(_streamItem.imgUrl),
fit: BoxFit.cover)
)
)
Any ideas?
I think you can consider using Positioned widget - it has width and height property. We can combine these widgets: Positioned > ClipRect > BackdropFilter. Please refer to the Gist: https://gist.github.com/anticafe/dc84cf6488d9defea437b702b13e2749#file-blur_multiple_widgets_with_dynamic_region-dart
Let take a look at this article to see more about BackdropFilter.
You can explicitly give a fix height to the container that contains the image, which will even look better.
In this example I have set three images of very different dimensions and has no problem rendering.
Refer the below code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('So Help'),
),
body: new ListView(
children: <Widget>[
MyContainer(
imageUrl:
'https://i.dailymail.co.uk/i/pix/2017/01/16/20/332EE38400000578-4125738-image-a-132_1484600112489.jpg',
),
MyContainer(
imageUrl:
'http://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2014/4/11/1397210130748/Spring-Lamb.-Image-shot-2-011.jpg',
),
MyContainer(
imageUrl:
'http://wackymania.com/image/2011/6/vertical-panoramic-photography/vertical-panoramic-photography-15.jpg',
),
],
),
);
}
}
class MyContainer extends StatelessWidget {
final String imageUrl;
MyContainer({#required this.imageUrl});
#override
Widget build(BuildContext context) {
return new Container(
height: 300.0,
child: new Stack(
children: <Widget>[
new Container(
child: Image.network(
this.imageUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
),
BackdropFilter(
filter: Dui.ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: new Container(
color: Colors.transparent,
),
),
new Container(
height: 300.0,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(
'Header',
style: new TextStyle(color: Colors.white),
),
),
new Expanded(
child: Image.network(imageUrl),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(
'Footer',
style: new TextStyle(color: Colors.white),
),
),
],
),
)
],
),
);
}
}

Android TextView's Lines equivalent in flutter

So, I need to make a Text widget to have an exact number of lines. In android studio, I only need to add property android:Lines = 2 and then the TextView will be 2 lines, regardless of how long the text is (if less than 2 lines, then fill the second line with an empty space) and regardless of what's the user's device font size.
The problem is, I have difficulty in replicating such behavior in flutter dynamically. The screenshot below works only on a particular user device's fontSize, since it uses an exact height (32.0).
new Container(
height: 32.0,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Expanded(
child: new Text('Curry Rice'), maxLines: 2, overflow: TextOverflow.ellipsis))
])
)
The problem arise when user is increasing / decreasing their device's font size, it will make the fixed-height container's doesn't work anymore.
So, any idea how to replicate android:Lines behavior in flutter Text widget regardless of the user's device text size?
UPDATE: Added comprehensive code for better context
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
return new MaterialApp(
title: 'App Title',
theme:
new ThemeData(primaryColor: Colors.white, accentColor: Colors.blue),
home: new Scaffold(
appBar: new AppBar(
title: new Text('App Title'),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list), onPressed: null),
],
),
body: new Center(
child: new Padding(
padding: new EdgeInsets.all(16.0),
child: new TestWidget()))));
}
}
class TestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new SizedBox(
width: 150.0,
child: new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Image.asset(
'assets/thumb2.jpg',
color: Colors.red,
),
new InkWell(
onTap: () {
// _showMenuDescription(context);
},
child: new Padding(
padding: new EdgeInsets.all(8.0),
child: new Column(
children: <Widget>[
new Container(
height: 32.0,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Expanded(
child: new Text(
'Curry Rice With Tandoori Chicken and Sunny Side Fried Egg',
maxLines: 2,
overflow: TextOverflow.ellipsis),
)
]),
),
new Container(height: 8.0),
new Row(
children: <Widget>[
new Expanded(
child: new Text(
'BBQ Sauce',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: new TextStyle(color: Colors.black45),
),
),
new Padding(
padding: new EdgeInsets.only(left: 8.0),
child: new Text(
'20,000',
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: new TextStyle(
color: const Color(0xffffa000)),
))
],
),
],
))),
],
),
));
}
}
The problem is that you are setting a finite height for your column. And that height is not enough to display 2 lines with this text style.
Increase the column height or remove that constraint entirely should solve the problem.

Categories

Resources