I am using flutter to design UI with sidebar navigation, which will be collapsed (icon only) by default and show the labels when expanded.
When the sidebar is expanded, it flickers an error
A RenderFlex overflowed by 4.3 pixels on the right.
Here is the code used for the sidebar
import 'package:flutter/material.dart';
import '../constants/colors.dart';
import 'button.dart';
class Sidebar extends StatefulWidget {
final bool showSidebar;
/// If [showSidebar] true, sidebar will be display in expanded mode.
/// Default is collapsed.
const Sidebar({
Key? key,
this.showSidebar = false
}) : super(key: key);
@override
State<Sidebar> createState() => _SidebarState();
}
class _SidebarState extends State<Sidebar> {
late bool _showSidebar;
@override
void initState() {
super.initState();
setState(() {
_showSidebar = widget.showSidebar;
});
}
@override
Widget build(BuildContext context) {
return
AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: widget.showSidebar ? 200 : 60,
decoration: BoxDecoration(
color: ThemeColors.primary,
borderRadius: const BorderRadius.all(Radius.circular(10))
),
onEnd: () {
setState(() {
_showSidebar = widget.showSidebar;
print(_showSidebar);
});
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 15),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Button(
onPressed: () {},
type: ButtonType.transparent,
icon: Icons.home,
label: 'Home',
iconOnly: !_showSidebar,
),
Column(
children: [
Button(
icon: Icons.person_2_outlined,
label: 'Profile',
type: ButtonType.transparent,
iconOnly: !_showSidebar,
onPressed: () {},
),
Button(
icon: Icons.chat,
label: 'Chat',
type: ButtonType.transparent,
iconOnly: !_showSidebar,
onPressed: () {},
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Divider(color: ThemeColors.primaryText,),
),
Button(
icon: Icons.show_chart,
label: 'Chart',
type: ButtonType.transparent,
iconOnly: !_showSidebar,
onPressed: () {},
),
Button(
icon: Icons.pie_chart,
label: 'Pie Chart',
type: ButtonType.transparent,
iconOnly: !_showSidebar,
onPressed: () {},
),
],
),
Button(
icon: Icons.settings,
label: 'Settings',
type: ButtonType.transparent,
iconOnly: !_showSidebar,
onPressed: () {},
),
],
),
),
);
}
}
and button.dart
/// Support button theme
enum ButtonType {
success,
primary,
secondary,
danger,
transparent
}
class Button extends StatelessWidget {
final VoidCallback onPressed;
final String? label;
final IconData? icon;
final ButtonType? type;
final bool? iconOnly;
/// Creates a new button widget.
///
/// The [onPressed] callback must not be null.
///
/// If [iconOnly] is true, the button will display only an icon.
///
/// If [type] is not specified, the primary button type will be used.
const Button({
Key? key,
required this.onPressed,
this.label,
this.icon,
this.iconOnly = false,
this.type = ButtonType.primary
}) : super(key: key);
@override
Widget build(BuildContext context) {
return iconOnly! ?
IconButton(
onPressed: onPressed,
icon: Icon(icon!, color: _getTextColor(),),
) : ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: _getColor(),
foregroundColor: _getTextColor(),
elevation: _getColor() == Colors.transparent ? 0 : 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
)
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
children: [
if (icon != null)
Icon(icon!, color: _getTextColor(),),
if (label != null)
const SizedBox(width: 8,),
Text(label!, style: TextStyle(color: _getTextColor()),),
],
),
),
);
}
/// Get color by button type
_getColor() {
switch (type) {
case ButtonType.success:
return ThemeColors.success;
case ButtonType.primary:
return ThemeColors.primary;
case ButtonType.secondary:
return ThemeColors.secondary;
case ButtonType.danger:
return ThemeColors.danger;
case ButtonType.transparent:
return Colors.transparent;
default:
return ThemeColors.primary;
}
}
_getTextColor() {
switch (type) {
case ButtonType.success:
return ThemeColors.white;
case ButtonType.primary:
return ThemeColors.primaryText;
case ButtonType.secondary:
return ThemeColors.white;
case ButtonType.danger:
return ThemeColors.white;
case ButtonType.transparent:
return ThemeColors.primaryText;
default:
return ThemeColors.primaryText;
}
}
}
2
Answers
Some Text widgets in the Button class are overflowed during the Sidebar animation. You should set its overflow property for them in your Button class.
Hope this helps.
The problem here is the size of sidebar is provided (200 or 60). You should try to avoid that.
I have come up with some solution using AnimatedSwitcher.
Output:
https://youtube.com/shorts/OFzCJy7jwIc?feature=share