null safety on widget parameter - flutter

Before null-safety, I can pass widget, if check it is null, will show other widget. On null-safety environment, is there a way if I didn't pass widget image or note?
class Message extends StatelessWidget {
const Message({
Key key,
this.image,
this.title = "",
this.subtitle = "",
this.note,
this.onTap
}) : super(key: key);
final Widget image;
final String title;
final String subtitle;
final Widget note;
final Function onTap
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Column(
children:[
image ?? Container(),
if(note != null) note
]
)
);
}
};

Use ? if the child can be null.
class FooWidget extends StatelessWidget {
final Widget? child; // <-- Nullable, use '?'
FooWidget({
this.child,
});
// ...
}
Use required if the child can't be null.
class FooWidget extends StatelessWidget {
final Widget child; // <-- Non-nullable
FooWidget({
required this.child, // <-- Use 'required'
});
// ...
}

You can declare your image and note as nullable types. If you need to make any of the field mandatory, you can mark it as required.
class Message extends StatelessWidget {
const Message({
Key? key,
this.image,
this.title = "",
this.subtitle = "",
this.note,
required this.onTap,
}) : super(key: key);
final Widget? image;
final String title;
final String subtitle;
final Widget? note;
final VoidCallback onTap;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Column(
children:[
image ?? Container(),
note ?? Container(),
]
)
);
}
}

Related

Trying make a status based on a boolean value to change an icon to tick in Dart

Need to make a status based on a boolean value to change an icon to tick
if it is true and do nothing if its false. Tried to make logic but something not
working well. Please help.
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar( {Key? key, required this.title, required this.status}) : super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
#override
Widget build(BuildContext context) {
return Row(
children: [
Text('${widget.title}'),
IconButton(
icon: true
? Icon(Icons.favorite_border)
: Icon(
Icons.favorite,
),
onPressed: () {
setState(() {
// Here we changing the icon.
var status = !true;
});
}),
],
);
}
}
Since you are getting the status in stateful widget, you can use it as widget.status and check using ternary operator ? :
Example
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar( {Key? key, required this.title, required this.status}) : super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
late bool status;
#override
void initState() {
status = widget.status;
super.initState();
}
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text('${widget.title}'),
IconButton(
icon: Icon(status ? Icons.favorite : Icons.favorite_border),
onPressed: () {
setState(() {
status = !status;
});
}),
],
);
}
}
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar( {Key? key, required this.title, required this.status}) : super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
bool initialStatus=widget.status;
#override
Widget build(BuildContext context) {
return Row(
children: [
Text('${widget.title}'),
IconButton(
icon: initialStatus
? Icon(Icons.favorite_border)
: Icon(
Icons.favorite,
),
onPressed: () {
setState(() {
// Here we changing the icon.
initialStatus = !initialStatus;
});
}),
],
);
}
}
class _OrderStatusBarState extends State<OrderStatusBar> {
bool _favoriteStatus = widget.status;
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text('${widget.title}'),
IconButton(
icon: _favoriteStatus ? const Icon(Icons.favorite) : const Icon(Icons.favorite_border),
onPressed: () {
setState(() {
_favoriteStatus = !_favoriteStatus;
});
}),
],
);
}
}
You need to store the status in your state widget and toggle the boolean when clicking on the icon.
Also, you can access the fields of the widget from its state through the widget property of the state.
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar({Key? key, required this.title, required this.status}) : super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
late bool status;
#override
void initState() {
super.initState();
status = widget.status; // you will need to implement the initState() function as the `widget`
// property cannot be accessed during the instance initialization
}
#override
Widget build(BuildContext context) {
return Row(children: [
Text(widget.title),
IconButton(
icon: status ? const Icon(Icons.favorite_border) : const Icon(Icons.favorite),
onPressed: () {
setState(() {
status = !status; // here we toggle the status field of the state widget
});
})
]);
}
}

How to increase the width of a PopupMenuEntry in flutter

I created a horizontal popup menu but i cant increase the width of the popupMenuEntry because the default width is too short for my use case. I tried to set the child of my popupMenuEntry to double.infinity and MediaQuery.of(context).sized.width but nothing is happening..
It looks like ok in the emulator but when i tested out in the actual device, its too small thats why i need to resize it to at least 90-95% of the screen width.
here is my implementation of my popupMenu.
class ReactionPopupMenu extends StatefulWidget {
const ReactionPopupMenu(
{Key? key, required this.onSelect, required this.child, this.onTap})
: super(key: key);
final void Function(String) onSelect;
final Widget child;
final VoidCallback? onTap;
#override
State<ReactionPopupMenu> createState() => _ReactionPopupMenuState();
}
class _ReactionPopupMenuState extends State<ReactionPopupMenu>
with CustomPopupMenu {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
onTapDown: storePosition,
onLongPress: () => this.showMenu(
context: context,
shape: const StadiumBorder(),
items: [
CustomedPopupEntry(
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
for (var i = 0; i < kEmojies.length; i++)
ReactiveEmoji(
emoji: kEmojies[i],
onTap: () =>
Navigator.pop(context, kValue[i]))
]),
),
)
]).then(
(value) => value == null ? null : widget.onSelect(value)),
child: widget.child);
}
}
mixin CustomPopupMenu<T extends StatefulWidget> on State<T> {
Offset? _tapPosition;
/// Pass this method to an onTapDown parameter to record the tap position.
void storePosition(TapDownDetails details) =>
_tapPosition = details.globalPosition;
/// Use this method to show the menu.
// ignore: avoid_shadowing_type_parameters
Future<T?> showMenu<T>({
required BuildContext context,
required List<PopupMenuEntry<T>> items,
T? initialValue,
double? elevation,
String? semanticLabel,
ShapeBorder? shape,
Color? color,
bool captureInheritedThemes = true,
bool useRootNavigator = false,
}) {
// final RenderObject? overlay =
// Overlay.of(context)!.context.findRenderObject();
return material.showMenu<T>(
context: context,
position: RelativeRect.fromLTRB(
_tapPosition!.dx,
_tapPosition!.dy,
_tapPosition!.dx,
_tapPosition!.dy,
),
items: items,
initialValue: initialValue,
elevation: elevation,
semanticLabel: semanticLabel,
shape: shape,
color: color,
useRootNavigator: useRootNavigator,
);
}
}
class CustomedPopupEntry<T> extends PopupMenuEntry<T> {
const CustomedPopupEntry({Key? key, required this.child}) : super(key: key);
final Widget child;
#override
State<StatefulWidget> createState() => _CustomedPopupEntryState();
#override
double get height => 100;
#override
bool represents(T? value) => false;
}
class _CustomedPopupEntryState extends State<CustomedPopupEntry> {
#override
Widget build(BuildContext context) => widget.child;
}
class ReactiveEmoji extends StatelessWidget {
const ReactiveEmoji({Key? key, required this.emoji, required this.onTap})
: super(key: key);
final String emoji;
final VoidCallback onTap;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: MediaQuery.of(context).size.width * 0.046,
backgroundImage: AssetImage(emoji),
),
);
}
}
Your solution is not with adding more width to popUpMenu. you should make your emoji list scrollable, so when use it in small device it could be scrolled. So wrap your emoji row with SingleChildScrollView and set its scrollDirection to horizontal.

Flutter: build a container with child parameter of type Text

I am new to Flutter. I would like to make a container that takes Text as parameter. How can I do that?
Here's my code:
class TopBar extends StatefulWidget {
final Text text;
TopBar({
Key key,
this.text,
}) : super(key: key);
_TopBarState _TopBarState = _TopBarState();
#override
_TopBarState createState() {
return this._TopBarState = _TopBarState();
}
}
class _TopBarState extends State<TopBar> {
#override
Widget build(BuildContext context) {
return Align(
child: Container(
child: Row(
children: [
// how to add parametrized text here?
],
),
),
),
);
}
}
Thank you!
Keep the datatype to String and not Text. You can access the value with widget.text in the widget. You can however keep the datatype as text, but you'll have to pass a Text widget.
Here's the code:
class TopBar extends StatefulWidget {
final String text;
TopBar({
Key key,
this.text,
}) : super(key: key);
_TopBarState _TopBarState = _TopBarState();
#override
_TopBarState createState() {
return this._TopBarState = _TopBarState();
}
}
class _TopBarState extends State<TopBar> {
#override
Widget build(BuildContext context) {
return Align(
child: Container(
child: Row(
children: [
Text(widget.text),
],
),
),
),
);
}
}

In Flutter Is it possible to show the image and the video in the same widget, Are there any common widget?

I want to show the image and the video in the common widget, Are there any common widget in the flutter to show image and the video.
I don't think there are any such widgets in-built flutter.
You can create a custom widget.PhotoVideoViewWidget as shown in the code.
class PhotoVideoViewWidget extends StatelessWidget {
final String type;
final String url;
const PhotoVideoViewWidget({Key key, this.type, this.url}) : super(key: key);
#override
Widget build(BuildContext context) {
return type == "video"
? VideoViewWidget(
videoUrl: url,
)
: PhotoViewWidget(
imageUrl: url,
);
}
}
class PhotoViewWidget extends StatelessWidget {
final String imageUrl;
const PhotoViewWidget({Key key, this.imageUrl}) : super(key: key);
#override
Widget build(BuildContext context) {
return PhotoViewer(imageUrl);
}
}
class VideoViewWidget extends StatelessWidget {
final String videoUrl;
const VideoViewWidget({Key key, this.videoUrl}) : super(key: key);
#override
Widget build(BuildContext context) {
return VideoViewer(videoUrl);
}
}

Create a event (like on tap) for a Custom widget

I am creating my custom widget in which I am using RaisedButton
I want to export onTap event from RaisedButton to parent widget. How can I do that?
Create a custom widget:
class MyCustomWidget extends StatelessWidget {
final String text;
final VoidCallback? onTap;
const MyCustomWidget(this.text, {
Key? key,
this.onTap,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onTap,
child: Text(text),
);
}
}
Usage:
MyCustomWidget(
'My button',
onTap: () {},
)