pub struct Flex<T> { /* private fields */ }
Expand description
A container with either horizontal or vertical layout.
This widget is the foundation of most layouts, and is highly configurable.
Flex layout algorithm
Children of a Flex
container can have an optional flex
parameter.
Layout occurs in several passes. First we measure (calling their layout
method) our non-flex children, providing them with unbounded space on the
main axis. Next, the remaining space is divided between the flex children
according to their flex factor, and they are measured. Unlike a non-flex
child, a child with a non-zero flex factor has a maximum allowed size
on the main axis; non-flex children are allowed to choose their size first,
and freely.
If you would like a child to be forced to use up all of the flex space
passed to it, you can place it in a SizedBox
set to expand
in the
appropriate axis. There are convenience methods for this available on
WidgetExt
: expand_width
and expand_height
.
Flex or non-flex?
When should your children be flexible? With other things being equal, a flexible child has lower layout priority than a non-flexible child. Imagine, for instance, we have a row that is 30dp wide, and we have two children, both of which want to be 20dp wide. If child #1 is non-flex and child #2 is flex, the first widget will take up its 20dp, and the second widget will be constrained to 10dp.
If, instead, both widgets are flex, they will each be given equal space, and both will end up taking up 15dp.
If both are non-flex they will both take up 20dp, and will overflow the container.
-------non-flex----- -flex-----
| child #1 | child #2 |
----flex------- ----flex-------
| child #1 | child #2 |
In general, if you are using widgets that are opinionated about their size (such as most control widgets, which are designed to lay out nicely together, or text widgets that are sized to fit their text) you should make them non-flexible.
If you are trying to divide space evenly, or if you want a particular item to have access to all left over space, then you should make it flexible.
note: by default, a widget will not necessarily use all the space that
is available to it. For instance, the TextBox
widget has a default
width, and will choose this width if possible, even if more space is
available to it. If you want to force a widget to use all available space,
you should expand it, with expand_width
or expand_height
.
Options
To experiment with these options, see the flex
example in druid/examples
.
-
CrossAxisAlignment
determines how children are positioned on the cross or ‘minor’ axis. The default isCrossAxisAlignment::Center
. -
MainAxisAlignment
determines how children are positioned on the main axis; this is only meaningful if the container has more space on the main axis than is taken up by its children. -
must_fill_main_axis
determines whether the container is obliged to be maximally large on the major axis, as determined by its own constraints. If this istrue
, then the container must fill the available space on that axis; otherwise it may be smaller if its children are smaller.
Additional options can be set (or overridden) in the FlexParams
.
Examples
Construction with builder methods
use druid::widget::{Flex, FlexParams, Label, Slider, CrossAxisAlignment};
let my_row = Flex::row()
.cross_axis_alignment(CrossAxisAlignment::Center)
.must_fill_main_axis(true)
.with_child(Label::new("hello"))
.with_default_spacer()
.with_flex_child(Slider::new(), 1.0);
Construction with mutating methods
use druid::widget::{Flex, FlexParams, Label, Slider, CrossAxisAlignment};
let mut my_row = Flex::row();
my_row.set_must_fill_main_axis(true);
my_row.set_cross_axis_alignment(CrossAxisAlignment::Center);
my_row.add_child(Label::new("hello"));
my_row.add_default_spacer();
my_row.add_flex_child(Slider::new(), 1.0);
Implementations§
§impl<T> Flex<T>where
T: Data,
impl<T> Flex<T>where T: Data,
pub fn row() -> Flex<T>
pub fn row() -> Flex<T>
Create a new horizontal stack.
The child widgets are laid out horizontally, from left to right.
pub fn column() -> Flex<T>
pub fn column() -> Flex<T>
Create a new vertical stack.
The child widgets are laid out vertically, from top to bottom.
pub fn cross_axis_alignment(self, alignment: CrossAxisAlignment) -> Flex<T>
pub fn cross_axis_alignment(self, alignment: CrossAxisAlignment) -> Flex<T>
Builder-style method for specifying the childrens’ CrossAxisAlignment
.
pub fn main_axis_alignment(self, alignment: MainAxisAlignment) -> Flex<T>
pub fn main_axis_alignment(self, alignment: MainAxisAlignment) -> Flex<T>
Builder-style method for specifying the childrens’ MainAxisAlignment
.
pub fn must_fill_main_axis(self, fill: bool) -> Flex<T>
pub fn must_fill_main_axis(self, fill: bool) -> Flex<T>
Builder-style method for setting whether the container must expand to fill the available space on its main axis.
If any children have flex then this container will expand to fill all available space on its main axis; But if no children are flex, this flag determines whether or not the container should shrink to fit, or must expand to fill.
If it expands, and there is extra space left over, that space is
distributed in accordance with the MainAxisAlignment
.
The default value is false
.
pub fn with_child(self, child: impl Widget<T> + 'static) -> Flex<T>
pub fn with_child(self, child: impl Widget<T> + 'static) -> Flex<T>
Builder-style variant of add_child
.
Convenient for assembling a group of widgets in a single expression.
pub fn with_flex_child(
self,
child: impl Widget<T> + 'static,
params: impl Into<FlexParams>
) -> Flex<T>
pub fn with_flex_child( self, child: impl Widget<T> + 'static, params: impl Into<FlexParams> ) -> Flex<T>
Builder-style method to add a flexible child to the container.
This method is used when you need more control over the behaviour
of the widget you are adding. In the general case, this likely
means giving that child a ‘flex factor’, but it could also mean
giving the child a custom CrossAxisAlignment
, or a combination
of the two.
This function takes a child widget and FlexParams
; importantly
you can pass in a float as your FlexParams
in most cases.
For the non-builder variant, see add_flex_child
.
Examples
use druid::widget::{Flex, FlexParams, Label, Slider, CrossAxisAlignment};
let my_row = Flex::row()
.with_flex_child(Slider::new(), 1.0)
.with_flex_child(Slider::new(), FlexParams::new(1.0, CrossAxisAlignment::End));
pub fn with_default_spacer(self) -> Flex<T>
pub fn with_default_spacer(self) -> Flex<T>
Builder-style method to add a spacer widget with a standard size.
The actual value of this spacer depends on whether this container is a row or column, as well as theme settings.
pub fn with_spacer(self, len: impl Into<KeyOrValue<f64>>) -> Flex<T>
pub fn with_spacer(self, len: impl Into<KeyOrValue<f64>>) -> Flex<T>
Builder-style method for adding a fixed-size spacer to the container.
If you are laying out standard controls in this container, you should
generally prefer to use add_default_spacer
.
pub fn with_flex_spacer(self, flex: f64) -> Flex<T>
pub fn with_flex_spacer(self, flex: f64) -> Flex<T>
Builder-style method for adding a flex
spacer to the container.
pub fn set_cross_axis_alignment(&mut self, alignment: CrossAxisAlignment)
pub fn set_cross_axis_alignment(&mut self, alignment: CrossAxisAlignment)
Set the childrens’ CrossAxisAlignment
.
pub fn set_main_axis_alignment(&mut self, alignment: MainAxisAlignment)
pub fn set_main_axis_alignment(&mut self, alignment: MainAxisAlignment)
Set the childrens’ MainAxisAlignment
.
pub fn set_must_fill_main_axis(&mut self, fill: bool)
pub fn set_must_fill_main_axis(&mut self, fill: bool)
Set whether the container must expand to fill the available space on its main axis.
pub fn add_child(&mut self, child: impl Widget<T> + 'static)
pub fn add_child(&mut self, child: impl Widget<T> + 'static)
Add a non-flex child widget.
See also with_child
.
pub fn add_flex_child(
&mut self,
child: impl Widget<T> + 'static,
params: impl Into<FlexParams>
)
pub fn add_flex_child( &mut self, child: impl Widget<T> + 'static, params: impl Into<FlexParams> )
Add a flexible child widget.
This method is used when you need more control over the behaviour
of the widget you are adding. In the general case, this likely
means giving that child a ‘flex factor’, but it could also mean
giving the child a custom CrossAxisAlignment
, or a combination
of the two.
This function takes a child widget and FlexParams
; importantly
you can pass in a float as your FlexParams
in most cases.
For the builder-style variant, see with_flex_child
.
Examples
use druid::widget::{Flex, FlexParams, Label, Slider, CrossAxisAlignment};
let mut my_row = Flex::row();
my_row.add_flex_child(Slider::new(), 1.0);
my_row.add_flex_child(Slider::new(), FlexParams::new(1.0, CrossAxisAlignment::End));
pub fn add_default_spacer(&mut self)
pub fn add_default_spacer(&mut self)
Add a spacer widget with a standard size.
The actual value of this spacer depends on whether this container is a row or column, as well as theme settings.
pub fn add_spacer(&mut self, len: impl Into<KeyOrValue<f64>>)
pub fn add_spacer(&mut self, len: impl Into<KeyOrValue<f64>>)
Add an empty spacer widget with the given size.
If you are laying out standard controls in this container, you should
generally prefer to use add_default_spacer
.
pub fn add_flex_spacer(&mut self, flex: f64)
pub fn add_flex_spacer(&mut self, flex: f64)
Add an empty spacer widget with a specific flex
factor.
Trait Implementations§
§impl<T> Widget<T> for Flex<T>where
T: Data,
impl<T> Widget<T> for Flex<T>where T: Data,
§fn event(
&mut self,
ctx: &mut EventCtx<'_, '_>,
event: &Event,
data: &mut T,
env: &Env
)
fn event( &mut self, ctx: &mut EventCtx<'_, '_>, event: &Event, data: &mut T, env: &Env )
§fn lifecycle(
&mut self,
ctx: &mut LifeCycleCtx<'_, '_>,
event: &LifeCycle,
data: &T,
env: &Env
)
fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, data: &T, env: &Env )
§fn layout(
&mut self,
ctx: &mut LayoutCtx<'_, '_>,
bc: &BoxConstraints,
data: &T,
env: &Env
) -> Size
fn layout( &mut self, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> Size
§fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, data: &T, env: &Env)
fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, data: &T, env: &Env)
§fn compute_max_intrinsic(
&mut self,
axis: Axis,
ctx: &mut LayoutCtx<'_, '_>,
bc: &BoxConstraints,
data: &T,
env: &Env
) -> f64
fn compute_max_intrinsic( &mut self, axis: Axis, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> f64
Auto Trait Implementations§
impl<T> !RefUnwindSafe for Flex<T>
impl<T> !Send for Flex<T>
impl<T> !Sync for Flex<T>
impl<T> Unpin for Flex<T>where T: Unpin,
impl<T> !UnwindSafe for Flex<T>
Blanket Implementations§
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> RoundFrom<T> for T
impl<T> RoundFrom<T> for T
§fn round_from(x: T) -> T
fn round_from(x: T) -> T
§impl<T, U> RoundInto<U> for Twhere
U: RoundFrom<T>,
impl<T, U> RoundInto<U> for Twhere U: RoundFrom<T>,
§fn round_into(self) -> U
fn round_into(self) -> U
§impl<T, W> TestWidgetExt<T> for Wwhere
T: Data,
W: Widget<T> + 'static,
impl<T, W> TestWidgetExt<T> for Wwhere T: Data, W: Widget<T> + 'static,
§impl<T, W> WidgetExt<T> for Wwhere
T: Data,
W: Widget<T> + 'static,
impl<T, W> WidgetExt<T> for Wwhere T: Data, W: Widget<T> + 'static,
§fn align_left(self) -> Align<T>
fn align_left(self) -> Align<T>
Align
widget, configured to align left.§fn align_right(self) -> Align<T>
fn align_right(self) -> Align<T>
Align
widget, configured to align right.§fn align_vertical(self, align: UnitPoint) -> Align<T>
fn align_vertical(self, align: UnitPoint) -> Align<T>
Align
widget, configured to align vertically.§fn align_horizontal(self, align: UnitPoint) -> Align<T>
fn align_horizontal(self, align: UnitPoint) -> Align<T>
Align
widget, configured to align horizontally.§fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
SizedBox
with an explicit width.§fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
SizedBox
with an explicit height.§fn fix_size(
self,
width: impl Into<KeyOrValue<f64>>,
height: impl Into<KeyOrValue<f64>>
) -> SizedBox<T>
fn fix_size( self, width: impl Into<KeyOrValue<f64>>, height: impl Into<KeyOrValue<f64>> ) -> SizedBox<T>
SizedBox
with an explicit width and height§fn expand_width(self) -> SizedBox<T>
fn expand_width(self) -> SizedBox<T>
§fn expand_height(self) -> SizedBox<T>
fn expand_height(self) -> SizedBox<T>
§fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
§fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
§fn border(
self,
color: impl Into<KeyOrValue<Color>>,
width: impl Into<KeyOrValue<f64>>
) -> Container<T>
fn border( self, color: impl Into<KeyOrValue<Color>>, width: impl Into<KeyOrValue<f64>> ) -> Container<T>
§fn controller<C>(self, controller: C) -> ControllerHost<Self, C>where
C: Controller<T, Self>,
fn controller<C>(self, controller: C) -> ControllerHost<Self, C>where C: Controller<T, Self>,
Controller
.§fn on_added(
self,
f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static
) -> ControllerHost<Self, Added<T, Self>>
fn on_added( self, f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static ) -> ControllerHost<Self, Added<T, Self>>
§fn on_click(
self,
f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static
) -> ControllerHost<Self, Click<T>>
fn on_click( self, f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static ) -> ControllerHost<Self, Click<T>>
§fn debug_paint_layout(self) -> EnvScope<T, Self>
fn debug_paint_layout(self) -> EnvScope<T, Self>
layout
Rect
s of this widget and its children.§fn debug_widget_id(self) -> EnvScope<T, Self>
fn debug_widget_id(self) -> EnvScope<T, Self>
WidgetId
s for this widget and its children, when hot. Read more§fn debug_invalidation(self) -> DebugInvalidation<T, Self>
fn debug_invalidation(self) -> DebugInvalidation<T, Self>
§fn debug_widget(self) -> EnvScope<T, Self>
fn debug_widget(self) -> EnvScope<T, Self>
DEBUG_WIDGET
env variable for this widget (and its descendants). Read more§fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>
fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>
§fn disabled_if(
self,
disabled_if: impl Fn(&T, &Env) -> bool + 'static
) -> DisabledIf<T, Self>
fn disabled_if( self, disabled_if: impl Fn(&T, &Env) -> bool + 'static ) -> DisabledIf<T, Self>
DisabledIf
widget. Read more