How to constraint item position in flutter? - flutter

I try to make a list of widget. It look like this:
I know of no such thing as Constraint Layout in flutter. But I need something to position my arrow icon in a fixed position on the right. To put it simple, this is my widget code:
Row(
children:[
SizedBox(),
Column(),//this is all the item on the left
Spacer(),
Expanded(// this is the heart and arrow button
child: Column()
)
]
)
I notice that if my column on the left get too wide, my arrow and heart icon is shifted out of line.
How to put my icon in fixed position to the right?

here try this, You have to wrap middle column with expanded so it will take the maximum space available
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool isChecked = false;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (_, index) => Container(
padding: EdgeInsets.all(15),
margin: EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),border: Border.all(width: 1.5)),
child: Row(
children: [
Container(
width: 25,
height: 40,
color: Colors.black,
),
Expanded(
child: Column(children: [
//put your children here
]),
),
//this will be always on right
Column(
children: [
Icon(Icons.heart_broken),
Icon(Icons.chevron_right),
],
)
],
),
),
);
}
}

Related

Flutter stateful widget doesn't change container's color on condition?

In my app I generate a random number between 1-10 and i try to guess. I use container and text and gesture detector for it. I want containers to change color if i click on the right number which i generated randomly. But I don't know why i does not work i tried to solve but i could not. I used initstate or late variable but did not work. help me?
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key})
: super(
key: key,
);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Random random = Random();
late int guessNumber = random.nextInt(9) + 1;
#override
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("My App"),
centerTitle: true,
),
body: Column(
children: [
Expanded(
child: Row(
children: [
Expanded(child: Numb(1)),
Expanded(child: Numb(2)),
Expanded(child: Numb(3)),
],
),
),
Expanded(
child: Row(
children: [
Expanded(child: Numb(4)),
Expanded(child: Numb(5)),
Expanded(child: Numb(6)),
],
),
),
Expanded(
child: Row(
children: [
Expanded(child: Numb(7)),
Expanded(child: Numb(8)),
Expanded(child: Numb(9)),
],
),
),
],
));
}
Widget Numb(int numb) {
Color? color = Colors.lightGreen;
return GestureDetector(
onTap: () {
setState(() {
if (guessNumber == numb) {
color = Colors.pink;
}
});
},
child: Container(
margin: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: color,
),
child: Center(
child: Text(
numb.toString(),
style: const TextStyle(fontSize: 24),
),
),
),
);
}
}
The issue is color is inside the build method(while Numb(int numb) is inside build method) and keep getting Colors.lightGreen; on every setState. Put it outside the build method. like on
class _HomeScreenState extends State<HomeScreen> {
Random random = Random();
late int guessNumber = random.nextInt(9) + 1;
Color? color = Colors.lightGreen;

how to animate logo transition from appbar to drawer?

I want to have an animated staggered transition from the blue logo to the black logo when I open or slide the drawer.
Blue logo in SilverAppBar:
Black flutter logo:
I wonder if there is a way to make an animation to move the blue flutter logo to the drawer menu when clicking on hamburger menu or sliding the drawer and also while its moving i want it to change color, how can i do this?
Code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
bool _pinned = true;
bool _snap = false;
bool _floating = false;
// [SliverAppBar]s are typically used in [CustomScrollView.slivers], which in
// turn can be placed in a [Scaffold.body].
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
leading: IconButton(
icon: const Icon(Icons.menu,
size: 40), // change this size and style
onPressed: () => _scaffoldKey.currentState?.openDrawer(),
),
actions: const [
Padding(
padding: EdgeInsets.fromLTRB(5, 20, 80, 5),
)
],
pinned: _pinned,
snap: _snap,
floating: _floating,
expandedHeight: 160.0,
flexibleSpace: const FlexibleSpaceBar(
title: FlutterLogo(
size: 100,
),
),
),
],
),
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Center(child: Image.asset("assets/cib-flutter.png")),
)
],
),
));
}
}
Edit
I think i should not use Drawer() entirely and should make a custom animated transition from the SilverAppBar view to the right?
use hero widget I think
Like this :
in AppBar :
Hero(
child: Image.asset('your_img_path'),
tag: 'logo',
)
in Drawer :
Hero(
child: Image.asset('your_img_path'),
tag: 'logo',
)
check that they are the same tag to make the animation

Why can I not use children array here? Flutter

I have this class, taken and changed from one of the examples
class SignUpView extends StatelessWidget {
const SignUpView({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
),
);
}
}
But if I want to put children , instead of child, like this
class SignUpView extends StatelessWidget {
const SignUpView({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
children: [
SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
],
),
);
}
}
It says The named parameter children isn't defined.
What if I want to put more than one child in the Center container?
Center can only have a single child. Use something like Column, Row, or a ListView to use more than 1 widget for Center.
import 'package:flutter/material.dart';
class SignUpView extends StatelessWidget {
const SignUpView({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ListView(
children: [
SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
],
),
),
);
}
}

How can i make full menu come out while mouse hover in the AppBar in flutter?

This is what I am trying to achieve:
I've thought about onHover in MouseRegion widget and trying to see if this code works in body part.
I was going to implement this in AppBar in scaffold after i see this works in body part but i couldn't.
Does anyone know correct way?
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
showMenus(BuildContext context) async {
await showMenu(
context: context,
position: RelativeRect.fromLTRB(100, 100, 100, 100),
items: [
PopupMenuItem(
child: Text("View"),
),
PopupMenuItem(
child: Text("Edit"),
),
PopupMenuItem(
child: Text("Delete"),
),
],
);
}
#override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints.tight(Size(300.0, 200.0)),
child: MouseRegion(
onHover: showMenus(context),
child: Container(
color: Colors.lightBlueAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have entered or exited this box this many times:'),
],
),
),
),
);
}
}
Your only problem is incorrectly invoking the method.
On your MouseRegion onHover it should have a () => before invoking the method:
// the onHover event gives you an event object
onHover: (event) => showMenus(context),

Align widget center with AppBar bottom edge

I need to align a widget's center with the appbar bottom edge.
So it will be located vertically half on the appbar and half on the page body.
Right now I've added the widget into the AppBar bottom: but it wont align with it's horizontal center line.
Currently It looks like this:
While i want that the center of the SelectEnvironment button along with the horizontal white line will 'sit' exactly on the bottom edge of the appBar
The code for the appBar is like this:
class CustomAppBar extends AppBar {
final Widget appBarActionButton;
CustomAppBar({Widget title = AppUtils.EMPTY_TEXT_VIEW, this.appBarActionButton}): super(
title: title,
backgroundColor: Colors.blueGrey,
elevation: 0,
bottom: PreferredSize(
child: Stack( //The stack holds the horizontal line and the button aligned cente
alignment: Alignment.center,
children: <Widget>[
Container( //This is the horizontal line
color: Colors.GeneralDividerGray,
height: 1.0,
),
Align(
child: Container(
child: appBarActionButton, //This is the button widget
),
)
],
),
preferredSize: Size.fromHeight(4.0)),
);
}
If there a better way to achieve this by taking it outside of the appbar it's ok with me as long it will give the same effect.
I think you should use Stack and Column like this
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
typedef void OnWidgetSizeChange(Size size);
class MeasureSize extends StatefulWidget {
final Widget child;
final OnWidgetSizeChange onChange;
const MeasureSize({
Key key,
#required this.onChange,
#required this.child,
}) : super(key: key);
#override
_MeasureSizeState createState() => _MeasureSizeState();
}
class _MeasureSizeState extends State<MeasureSize> {
#override
Widget build(BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
return Container(
key: widgetKey,
child: widget.child,
);
}
var widgetKey = GlobalKey();
var oldSize;
void postFrameCallback(_) {
var context = widgetKey.currentContext;
if (context == null) return;
var newSize = context.size;
if (oldSize == newSize) return;
oldSize = newSize;
widget.onChange(newSize);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
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> {
Size s;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
MeasureSize(
onChange: (size) {
setState(() {
s = size;
});
},
child: AppBar(
title: Text('title'),
),
),
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - (s?.height ?? 0.0),
child: Center(child: Text('body')))
],
),
Positioned(
top: (s?.height ?? 0.0) - 16.0,
child: Container(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 32,
color: Colors.red[400],
padding: EdgeInsets.all(6),
child: Center(child: Text('Select Environment'))),
],
),
),
)
],
));
}
}
The best way is to use Slivers via a widget like below:
ScrollController scrollController = new ScrollController();
return Stack(
children: [
NestedScrollView(
controller: scrollController,
headerSliverBuilder: (context, value){
return [
// list of widgets in here
];
},
body: Container(
// here, your normal body goes
),
),
Positioned(
top: 50.0,
left: 100.0,
child: Container(
// your centered widget here
),
)
]
);
}
Instead of using a normal appBar, you have to use a SliverAppBar