Scroll single ListTile in ListView - flutter

Scroll single ListTile in ListView
class MainScreen extends MvcScreen<MainScreenController> {
#override
MainScreenController initController() => MainScreenController();
#override
Widget defaultScreenLayout(
ScreenParameters screenParameters, MainScreenController controller) {
return _tabsLayout;
}
Widget get _tabsLayout => DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text(AppScaffold().title),
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {}),
],
),
drawer: TelegramDrawer(),
floatingActionButton: FloatingActionButton(
backgroundColor: Color(0xff65a9e0),
child: Icon(Icons.create),
onPressed: () {},
),
body: _body,
),
);
Widget get _body => Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: _chatsListView),
],
).paddingAll(0);
Widget get _chatsListView => Container(
child:
ListView.builder(itemCount: 1, itemBuilder: channelListItemBuilder),
);
Widget channelListItemBuilder(context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blueGrey[200],
foregroundColor: Colors.white,
radius: 28,
child: Icon(
Icons.archive,
size: 30,
),
),
title: Text(
"Archived Chats",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
),
);
}

Once you wrap ListView in the column it does not allow you to scroll view. Therefore here I've changed the code:
Widget get _body => Expanded(child:Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: _chatsListView),
],
).paddingAll(0));

Related

Flutter: Prevent some children from getting stretched

Do you have an idea on how to prevent child from getting stretched.
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(child: ...),
Row( // idon't want this child to be stretched
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FlatButton(
child: Icon(Icons.add),
onPressed: () {},
color: Color(0xFFE2EDE4),
),
Text(
'$quantity',
style: Theme.of(context).textTheme.headline5.copyWith(
fontWeight: FontWeight.bold,
),
),
FlatButton(
child: Icon(Icons.remove),
onPressed: () {},
color: Color(0xFFE2EDE4),
),
],
),
],
);
I tried to wrap it in ConstrainedBox but still it is being stretched.
In this case, the crossAxisAlignment: CrossAxisAlignment.stretch property of Column don't affect to Row child. Instead of using mainAxisAlignment: MainAxisAlignment.spaceBetween
You can add SizedBox(width: ...)
If you want stretch Row widget, how about remove 'mainAxisAlignment' of Row.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(height: 200, color: Colors.blue, child: Text('123'),),
Column(
children: <Widget> [
Row( // idon't want this child to be stretched
children: [
FlatButton(
child: Icon(Icons.add),
onPressed: () {},
color: Color(0xFFE2EDE4),
),
Text(
'qweqe',
style: Theme.of(context).textTheme.headline5.copyWith(
fontWeight: FontWeight.bold,
),
),
FlatButton(
child: Icon(Icons.remove),
onPressed: () {},
color: Color(0xFFE2EDE4),
),
],
),
]),
],
);
}
}

Fixed buttons between AppBar and SingleChildScrollView (Flutter)

I would like to include buttons between AppBar and ListView. In the example below, the buttons scroll along with the text. I tried to include the SingleChildScrollView within a Column, but was unsuccessful.
I read that the Column widget does not support scrolling. I already searched a lot, but I didn't find an example similar to what I need.
Can someone help me?
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('A Idade do Lobo'),
elevation: 0.0,
backgroundColor: COLOR_MAIN,
),
body: NotificationListener(
onNotification: (notif) {
if (_hasScroll) {
if (notif is ScrollEndNotification && scrollOn) {
Timer(Duration(seconds: 1), () {
_scroll();
setState(() {
_controlButton();
});
});
}
}
return true;
},
child: SingleChildScrollView(
controller: _scrollController,
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Center(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new RaisedButton(
onPressed: _showScrollPickerDialog,
child: Text('Rolagem ${_scrollSpeed}'),
),
new RaisedButton(
onPressed: _showTomPickerDialog,
child: Text('TOM ${_tom}'),
),
],
),
),
new Flexible(
fit: FlexFit.loose,
child: new ListView.builder(
shrinkWrap: true,
itemCount: _songDetails.length,
itemBuilder: (context, index) {
return new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: new EdgeInsets.all(5.0),
child: new RichText(
text: TextSpan(children: [
new TextSpan(
text: '${_songDetails[index].line}',
style: _getStyle(
_songDetails[index].type,
),
),
]),
),
),
],
);
},
),
),
],
),
),
),
floatingActionButton: _controlButton(),
);
}
}
You can use bottom properly of AppBar to achieve desire UI.
Following example clear your idea.
import 'package:flutter/material.dart';
class DeleteWidget extends StatefulWidget {
const DeleteWidget({Key key}) : super(key: key);
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("your title"),
bottom: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 40),
child: Center(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new RaisedButton(
onPressed: () {},
child: Text('Rolagem '),
),
new RaisedButton(
onPressed: () {},
child: Text('TOM '),
),
],
),
),
),
),
body: Container(
child: ListView.builder(
itemBuilder: (context, int index) {
return Text(index.toString());
},
itemCount: 100,
),
));
}
}

Align text in centre of screen

I am trying to use Expand widget in Column so user can tap in any position of screen to increase counter, but there is an issue in alignment of text in crossAxisAlignment and mainAxisAlignment of the column it didn't apply on Expand widget as the following
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black12,
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
i++;
print(i);
});
},
child: Text(
i.toString(),
style: TextStyle(fontSize: 50.0, color: Colors.blueAccent),
textAlign: TextAlign.center,
),
),
),
],
),
),
),
),
);
You went with the wrong approach because you can't Center an Expanded because Expanded takes the entire available space inside Row or Column in your case Column with single Widget inside children the GestureDetector. Here is one of a solution for what you want to achieve
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black12,
body: SafeArea(
child: Center(
child: Stack(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: GestureDetector(
onTap: () {
setState(() => i++;);
},
),
),
],
),
Align(
alignment: Alignment.center,
child: Text(
'$i',
style: TextStyle(fontSize: 50.0, color: Colors.blueAccent),
),
),
],
),
),
),
);
}
another solution using FlatButton inside SizedBox.expand()
so you don't need to fight with a single child column.
class _MyAppState extends State<MyApp> {
int i = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black12,
body: SafeArea(
child: SizedBox.expand(
child: FlatButton(
onPressed: () {
setState(() {
i++;
print(i);
});
},
child: Text(
i.toString(),
style: TextStyle(fontSize: 50.0, color: Colors.blueAccent),
),
),
),
),
),
);
}
}

Is it possible to use a DropDownButton within an IconButton in Flutter?

Update:
#override
Widget build(BuildContext context) {
return new Container(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Container(
height: 220.0,
width: MediaQuery.of(context).size.width,
child: new GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Column(
children: <Widget>[
SizedBox(height: 40.0),
Row(
children: <Widget>[
Expanded(
child: Stack(
children: [
Center(
child: Text(
'Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lato',
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
),
Positioned(
right: 8,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 400)),
PopupMenuButton<String>(
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30.0,
),
onSelected: choiceAction,
itemBuilder: (BuildContext context) {
return Constants.choices.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
),
),
],
),
),
],
),
I am trying to implement a DropDownButton inside the OnPressed command of an IconButton, so that when the icon is pressed, a drop down menu is shown.
Update: I've updated my code with the suggestion made, however the icon does not appear.
I'm not sure if this is a problem with my widget tree.
Updated Answer
Please check this code:
class DropdownMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 400)),
PopupMenuButton<String>(
icon: Icon(Icons.settings),
onSelected: choiceAction,
itemBuilder: (BuildContext context) {
return Constants.choices.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
));
}
}
class Constants {
static const String FirstItem = 'First Item';
static const String SecondItem = 'Second Item';
static const String ThirdItem = 'Third Item';
static const List<String> choices = <String>[
FirstItem,
SecondItem,
ThirdItem,
];
}
void choiceAction(String choice) {
if (choice == Constants.FirstItem) {
print('I First Item');
} else if (choice == Constants.SecondItem) {
print('I Second Item');
} else if (choice == Constants.ThirdItem) {
print('I Third Item');
}
}
Note: This is not dropdown menu but i think this is what you want.
Old answer
You can try using showDialog
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.black,
size: 30.0,
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Country List'),
content: new ListView(
children: <Widget>[
new Column(
children: <Widget>[
new DropdownButton<String>(
items: <String>['A', 'B', 'C', 'D', 'E', 'F', 'G'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (_) {},
),
],
),
],
),
);
});
})
],
)

Expanded() widget not working in listview

I'm new to flutter. I'm trying to render a page whose body contains Listview with multiple widgets.
_buildOrderDetails widget in the listview is widget that is build with listview.builder() , remaining are normal widgets.
The problem is page is not being scrolled .
When the body Listview is changed to column and _buildOrderDetails is given as child to the Expanded, the listview is limited to some extent of the page height and being scrolled. But when input is focused the page is overflowed
Widget build(BuildContext context){
return ScopedModelDescendant<MainModel>(
builder: (BuildContext context, Widget child, MainModel model) {
return Scaffold(
appBar: AppBar(
title: Text('Order Details'),
actions: <Widget>[
IconButton(
onPressed: () {
model.addNewOrder();
},
icon: Icon(Icons.add),
),
BadgeIconButton(
itemCount: model.ordersCount,
badgeColor: Color.fromRGBO(37, 134, 16, 1.0),
badgeTextColor: Colors.white,
icon: Icon(Icons.shopping_cart, size: 30.0,),
onPressed: () {}
),
]
),
body: ListView(
children: [
Column(
children: [
_buildItemsTitle(),
Expanded(child: _buildOrderDetails(context, model)),
]
),
Card(
child: Column(
children:[
TextField(
decoration: InputDecoration(
labelText: 'Offer Code'
),
),
RaisedButton(
onPressed: (){},
child: Text('Apply'),
)
]
),
),
Card(child: _orderAmount(context, model),),
RaisedButton(
color: Theme.of(context).accentColor,
onPressed: (){},
child: Text('Checkout',
style: TextStyle(
fontSize: 20.0,
color: Colors.white
)
),
)
]
),);});}}
Maybe it can help someone in the future, but the trick seems to be: use ListView + LimitedBox(maxHeight) + Column ...
ListView(
padding: EdgeInsets.zero,
shrinkWrap: true,
children: [
FocusTraversalGroup(
child: Form(
key: _formKey,
child: LimitedBox(
maxHeight: MediaQuery.of(context).size.height,
child: Column(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Spacer(flex: 30), // Or Expanded
// More Widgets...
Spacer(flex: 70), // Or Expanded
// ....
Try not to use expanded on growing items. If you want to cover a percentage/fractional height wrap the height with a fixed height or the full height with a container that includes box contstains, then proceed to have expanded or fixed height children. also helpful is the FracionalBox
In the example you showed there is no need for expanded, the children inside will give a content height and the SingleChildScrollView will automaticly handle scrolling based on children.
Widget build(BuildContext context) {
return ScopedModelDescendant<MainModel>(
builder: (BuildContext context, Widget child, MainModel model) {
return Scaffold(
appBar: AppBar(title: Text('Order Details'), actions: <Widget>[
IconButton(
onPressed: () {
model.addNewOrder();
},
icon: Icon(Icons.add),
),
BadgeIconButton(
itemCount: model.ordersCount,
badgeColor: Color.fromRGBO(37, 134, 16, 1.0),
badgeTextColor: Colors.white,
icon: Icon(
Icons.shopping_cart,
size: 30.0,
),
onPressed: () {}),
]),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Column(children: [
_buildItemsTitle(),
Container(child: _buildOrderDetails(context, model)),
]),
Card(
child: Column(children: [
TextField(
decoration: InputDecoration(labelText: 'Offer Code'),
),
RaisedButton(
onPressed: () {},
child: Text('Apply'),
)
]),
),
Card(
child: _orderAmount(context, model),
),
RaisedButton(
color: Theme.of(context).accentColor,
onPressed: () {},
child: Text('Checkout',
style: TextStyle(fontSize: 20.0, color: Colors.white)),
),
],
),
),
);
});
}