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 is CrossAxisAlignment::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 is true, 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,

pub fn for_axis(axis: Axis) -> Flex<T>

Create a new Flex oriented along the provided axis.

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>

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>

Builder-style method for specifying the childrens’ CrossAxisAlignment.

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>

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>

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>

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>

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>

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>

Builder-style method for adding a flex spacer to the container.

pub fn set_cross_axis_alignment(&mut self, alignment: CrossAxisAlignment)

Set the childrens’ CrossAxisAlignment.

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)

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)

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> )

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)

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>>)

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)

Add an empty spacer widget with a specific flex factor.

Trait Implementations§

§

impl<T> Widget<T> for Flex<T>where T: Data,

§

fn event( &mut self, ctx: &mut EventCtx<'_, '_>, event: &Event, data: &mut T, env: &Env )

Handle an event. Read more
§

fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, data: &T, env: &Env )

Handle a life cycle notification. Read more
§

fn update( &mut self, ctx: &mut UpdateCtx<'_, '_>, _old_data: &T, data: &T, env: &Env )

Update the widget’s appearance in response to a change in the app’s Data or Env. Read more
§

fn layout( &mut self, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> Size

Compute layout. Read more
§

fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, data: &T, env: &Env)

Paint the widget appearance. Read more
§

fn compute_max_intrinsic( &mut self, axis: Axis, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> f64

Computes max intrinsic/preferred dimension of a widget on the provided axis. Read more

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§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = mem::align_of::<T>()

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> RoundFrom<T> for T

§

fn round_from(x: T) -> T

Performs the conversion.
§

impl<T, U> RoundInto<U> for Twhere U: RoundFrom<T>,

§

fn round_into(self) -> U

Performs the conversion.
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
§

impl<T, W> TestWidgetExt<T> for Wwhere T: Data, W: Widget<T> + 'static,

§

fn record(self, recording: &Recording) -> Recorder<Self>

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T, W> WidgetExt<T> for Wwhere T: Data, W: Widget<T> + 'static,

§

fn padding(self, insets: impl Into<KeyOrValue<Insets>>) -> Padding<T, Self>

Wrap this widget in a Padding widget with the given Insets. Read more
§

fn center(self) -> Align<T>

Wrap this widget in an Align widget, configured to center it.
§

fn align_left(self) -> Align<T>

Wrap this widget in an Align widget, configured to align left.
§

fn align_right(self) -> Align<T>

Wrap this widget in an Align widget, configured to align right.
§

fn align_vertical(self, align: UnitPoint) -> Align<T>

Wrap this widget in an Align widget, configured to align vertically.
§

fn align_horizontal(self, align: UnitPoint) -> Align<T>

Wrap this widget in an Align widget, configured to align horizontally.
§

fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>

Wrap this widget in a SizedBox with an explicit width.
§

fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>

Wrap this widget in a SizedBox with an explicit height.
§

fn fix_size( self, width: impl Into<KeyOrValue<f64>>, height: impl Into<KeyOrValue<f64>> ) -> SizedBox<T>

Wrap this widget in an SizedBox with an explicit width and height
§

fn expand(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width and height. Read more
§

fn expand_width(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width. Read more
§

fn expand_height(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width. Read more
§

fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>

Wrap this widget in a Container with the provided background brush. Read more
§

fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>

Wrap this widget in a Container with the provided foreground brush. Read more
§

fn border( self, color: impl Into<KeyOrValue<Color>>, width: impl Into<KeyOrValue<f64>> ) -> Container<T>

Wrap this widget in a Container with the given border. Read more
§

fn env_scope(self, f: impl Fn(&mut Env, &T) + 'static) -> EnvScope<T, Self>

Wrap this widget in a EnvScope widget, modifying the parent Env with the provided closure.
§

fn controller<C>(self, controller: C) -> ControllerHost<Self, C>where C: Controller<T, Self>,

Wrap this widget with the provided Controller.
§

fn on_added( self, f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static ) -> ControllerHost<Self, Added<T, Self>>

Provide a closure that will be called when this widget is added to the widget tree. Read more
§

fn on_click( self, f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static ) -> ControllerHost<Self, Click<T>>

Control the events of this widget with a Click widget. The closure provided will be called when the widget is clicked with the left mouse button. Read more
§

fn debug_paint_layout(self) -> EnvScope<T, Self>

Draw the layout Rects of this widget and its children.
§

fn debug_widget_id(self) -> EnvScope<T, Self>

Display the WidgetIds for this widget and its children, when hot. Read more
§

fn debug_invalidation(self) -> DebugInvalidation<T, Self>

Draw a color-changing rectangle over this widget, allowing you to see the invalidation regions.
§

fn debug_widget(self) -> EnvScope<T, Self>

Set the DEBUG_WIDGET env variable for this widget (and its descendants). Read more
§

fn lens<S, L>(self, lens: L) -> LensWrap<S, T, L, Self>where S: Data, L: Lens<S, T>,

Wrap this widget in a LensWrap widget for the provided Lens.
§

fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>

Assign the widget a specific WidgetId. Read more
§

fn boxed(self) -> Box<dyn Widget<T> + 'static, Global>

Wrap this widget in a Box.
§

fn scroll(self) -> Scroll<T, Self>

Wrap this widget in a Scroll widget.
§

fn disabled_if( self, disabled_if: impl Fn(&T, &Env) -> bool + 'static ) -> DisabledIf<T, Self>

Wrap this widget in a DisabledIf widget. Read more
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more