Evade flutter overflow when using row - flutter

[this is on desktop,not web or android]
I have following code, which creates a split screen (one side of screen has shortcuts to content and other side shows that content) it also acts somewhat as drawer since it can be closed or opened.
the left pane i reduce in one of two cases, when user clicks arrow button, or when the window side is less then 700. but if i try to take right edge of the screen and move very fast to reduce the size of whole window, the row will overflow and i will get an error.
So far i tryed using several things to achive this layout :
Using Flexible and setting fit and flex properties, (same issue as now since parent of them was again a row)
way that i am showing you now.
Also i could try to limit the size of screen lets say min value is 640 x 480 and that would also somewhat prevent error from happening.
I am just wondering is there another way to achieve this layout .
I also tryed several packages from pub.dev and ALL of them have same overflow error in their implementation .(easy_sidemenu,side_menu_navigation, etc)
my code
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: MyHomePage(
title: "My home",
),
);
}
}
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
final List<bool> isSelected = [false, false, false];
class _MyHomePageState extends ConsumerState<MyHomePage> {
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
elevation: 0,
toolbarHeight: 35,
centerTitle: true,
title: Text(widget.title),
),
body: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 500),
width: width > 700 ? 250 : 50,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 5),
children: [
TextButton(
onPressed: () {},
child: Row(
children: [
Icon(
Icons.home,
color: Theme.of(context).colorScheme.secondary,
size: 30,
),
const Flexible(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"Home",
maxLines: 1,
style:
TextStyle(overflow: TextOverflow.clip),
),
),
),
],
),
),
]),
),
const SizedBox(
height: 5,
),
TextButton(
onPressed: () {},
child: Row(
children: const [
Icon(
Icons.settings,
size: 30,
),
Flexible(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"Settings",
maxLines: 1,
style: TextStyle(overflow: TextOverflow.clip),
),
),
),
],
),
),
],
),
),
IconButton(onPressed: () {}, icon: const Icon(Icons.arrow_back)),
Expanded(
child: Container(
color: Colors.red,
)),
],
),
);
}
}

Related

How to scroll to active text field in bottom sheet?

Here is self contained code that demo's the issue I am seeing.
When i click to view bottom sheet, it shows correctly:
But when I click into a textfield, it doesn't scroll the sheet up.
How do I get the screen to ensure field is visible and scrolls to the active text field? From what I can tell, it seems like it's related to using the DefaultTabController. On other screens, I don't have the issue...but still need to find a solution to this specific use-case.
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
#override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
void showBottom() {
showModalBottomSheet(
context: context,
// isScrollControlled: true,
builder: (_) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
children: [
Text('testing bottom sheet.'),
TextFormField(),
TextFormField(),
TextFormField(),
],
),
);
});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('testing'),
bottom: TabBar(
indicatorColor: Colors.purple,
tabs: [
Tab(
child: Text(
'Zones',
style: TextStyle(color: Colors.black),
),
),
Text('My Profile', style: TextStyle(color: Colors.black))
],
),
),
body: TabBarView(
children: [
Container(
child: Text('Tab 1'),
),
Container(
child: Column(
children: [
Text('This is tab 2'),
TextButton(onPressed: (){
showBottom();
},child: Text('Show bottom'),)
],
),
)
],
),
));
}
}
Uncomment the line : isScrollControlled: true, this will allow the bottom sheet to take the space.

Create a new card when FAB is clicked

I need create a card, when the FAB is clicked, like a list or just create a card into Column, like this image:
enter image description here
Here's one way:
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()));
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> cardWidget = [];
buildCard() {
setState(() {
cardWidget.add(
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
RaisedButton(
onPressed: () {},
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0),
color: Colors.green,
child: Text(
'Criar',
style: TextStyle(
color: Colors.white
),
),
)
],
),
)
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[900],
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.blue[900]
),
floatingActionButton: FloatingActionButton(
onPressed: buildCard,
backgroundColor: Colors.green,
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: Column(
children: cardWidget.map((data) {
return data;
}).toList()
),
);
}
}
This method may not be the best way for you so I encourage you to try something new on your own!

Horizontal bar charts in Flutter

I'm trying to achieve a horizontal bar chart in flutter. I came across these packages fl_charts and charts_flutter. but I need to customise the looks to match with the following image I attached.
If any champ can support me in giving me steps to how to achieve this or an exemplary code will be so much helpful.
Thank you so much in advance.
Use LayoutBuilder to know the possible width, and IntrinsicWidth to calculate the place of title and numbers, but at the same time don't shrink the long title text.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_title('Food Weight(grams)'),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ChartLine(title: 'Fat', number: 1800, rate: 1),
ChartLine(title: 'Protein', number: 600, rate: 0.4)
],
),
),
_title('Ratios'),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ChartLine(
title: 'Calculum/Phosporous ratio = 2:1',
rate: 0.5,
),
ChartLine(
title: 'Omega3/6 ratio = 1:4',
rate: 0.4,
),
],
),
),
],
),
);
}
Widget _title(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0, top: 4),
child: Text(
title,
style: TextStyle(fontSize: 18),
),
);
}
}
class ChartLine extends StatelessWidget {
const ChartLine({
Key key,
#required this.rate,
#required this.title,
this.number,
}) : assert(title != null),
assert(rate != null),
assert(rate > 0),
assert(rate <= 1),
super(key: key);
final double rate;
final String title;
final int number;
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final lineWidget = constraints.maxWidth * rate;
return Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
constraints: BoxConstraints(minWidth: lineWidget),
child: IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
),
),
if (number != null)
Text(
number.toString(),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
Container(
color: Colors.blue,
height: 60,
width: lineWidget,
),
],
),
);
});
}
}
You can use the Syncfusion's Flutter charts package, as I am using now for my application. Using Syncfusion's SfCartesianChart widget, render the bar chart along with data labels and by changing the data label's default position your output can be achieved. This widget works on Android, iOS, and web platforms.
Package- https://pub.dev/packages/syncfusion_flutter_charts
Features- https://www.syncfusion.com/flutter-widgets/flutter-charts
Documentation- https://help.syncfusion.com/flutter/cartesian-charts/overview

Flutter : how to make an entire row clickable

How do I make the entire row clickable in flutter?. I have the following code wrap in a "GestureDetector". The individual items in the row are clickable but white space around the widget are not.
if ((auth.isLoggedIn)) ...[
GestureDetector(
onTap: () {
auth.signOut();
},
child: buildItem(
Image.asset("assets/images/logoff.png",),
"logout"
),
),
],
This is the "buildItem" method
Widget buildItem(Widget icon, String title) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 15),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: Row(
children: <Widget>[
icon,
SizedBox(width: 20.0),
Text(
title,
style: TextStyle(
fontSize: 16.0,
),
),
],
)),
Icon(
Icons.arrow_forward_ios,
size: 20.0,
),
],
),
);
}
This is the output. Each item in the row (icon, text and the >) respond to the tap gesture. However, the white space(e.g between the text and the ">") does not respond to tap
How can I make entire row respond to the tap.
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
///
},
replace GestureDetector with InkWell works great
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () {
print("click");
},
child: buildItem(
Image.network("https://picsum.photos/250?image=9",),
"logout"
),
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Widget buildItem(Widget icon, String title) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 15),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: Row(
children: <Widget>[
icon,
SizedBox(width: 20.0),
Text(
title,
style: TextStyle(
fontSize: 16.0,
),
),
],
)),
Icon(
Icons.arrow_forward_ios,
size: 20.0,
),
],
),
);
}
row: mainAxisAlignment: MainAxisAlignment.spaceBetween
For space between, the first and the last object will stick to the edge of the container, while leaving the empty unused space in between (if there is other objects, it will distributed it evenly), like shown in the screenshot below:
Hence to solve this, you just have to make sure that there is no empty space between.
One way is to use mainAxisSize: MainAxisSize.max and MainAxisAlignment.start in the Row where you put your icon and text.

How to center AppBar and how to reduce leading icon size in PrefrerredSize?

How to center whole AppBar and how to reduce leading icon?
I tried with Center widget and Column with mainAxisAlignment.center not working.
And I tried add width and height to leading icon container.but nothing is working
appBar: PreferredSize(
child: AppBar(
leading: Container(
decoration: BoxDecoration(..),
child: Icon(..),
),
title: TextFormField(
...
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
...
),
CupertinoSwitch(
...
)
],
)
],
),
preferredSize: Size.fromHeight(80.0)),
As shown here.
as an option
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AwesomeAppBar(height: 80),
),
);
}
}
class AwesomeAppBar extends PreferredSize {
final double height;
const AwesomeAppBar({Key key, #required this.height});
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, snapshot) {
return Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
height: height,
color: Theme.of(context).primaryColor,
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(16),
child: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
Expanded(
child: Container(
height: 32,
alignment: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16),
margin: EdgeInsets.only(right: 16),
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
color: Colors.white,
),
child: Text('Search'),
),
),
SwitchWithText(),
SizedBox(width: 16),
],
),
);
});
}
#override
Size get preferredSize => Size.fromHeight(height);
}
class SwitchWithText extends StatefulWidget {
#override
_SwitchWithTextState createState() => _SwitchWithTextState();
}
class _SwitchWithTextState extends State<SwitchWithText> {
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text('Online', style: TextStyle(color: Colors.white)),
CupertinoSwitch(
value: true,
onChanged: (b) {},
activeColor: Colors.lightBlueAccent,
),
],
);
}
}