SubAspectComponent class

A stateful widget rendering a responsive sub-video area with dynamic dimension management.

Displays a secondary video/content area (typically positioned at bottom-left) that adapts to screen dimensions and control visibility state. Commonly used for screenshare previews, mini video players, control overlays, or audio participant grids.

Lifecycle & State Management:

  • Tracks computed _width and _height based on screen size and configuration
  • Recalculates dimensions in didChangeDependencies() (screen rotation, initial build)
  • Recalculates dimensions in didUpdateWidget() when showControls, fractions, or defaultFractionSub change
  • Uses MediaQuery.of(context).size to get current screen dimensions

Rendering Pipeline:

1. Create Stack with children (clipBehavior applied)
2. Call contentBuilder (if provided) to wrap Stack
3. Build Container with:
   - Computed width (_width)
   - Computed height (_height if showControls=true, else 0)
   - Decoration (containerDecoration or backgroundColor)
   - Padding, margin, alignment
4. Call containerBuilder (if provided) to customize Container
5. Wrap in Positioned(bottom: 0, left: 0) for absolute positioning
6. Call wrapperBuilder (if provided) to customize positioning
7. Wrap in Visibility widget (visible only if showControls=true)

Dimension Calculation Details:

// Width calculation:
widthFraction = (containerWidthFraction ?? 1.0).clamp(0.0, 1.0);
_width = widthFraction * MediaQuery.of(context).size.width;

// Height calculation (only if showControls = true):
if (containerHeightFraction != null) {
  heightFraction = containerHeightFraction.clamp(0.0, 1.0);
  _height = heightFraction * screenHeight;
} else if (0 < defaultFractionSub <= 1) {
  _height = defaultFractionSub * screenHeight; // fractional mode
} else if (defaultFractionSub > 1) {
  _height = defaultFractionSub; // fixed pixel mode
} else {
  _height = 40; // minimum fallback
}

// When showControls = false:
_height = 0; (container collapses, Visibility hides entire widget)

Builder Hook Priorities:

  1. contentBuilder: Wrap Stack of children (e.g., add border around entire content area)
  2. containerBuilder: Customize Container with dimensions (e.g., apply gradient, adjust padding)
  3. wrapperBuilder: Customize Positioned widget (e.g., reposition from bottom-left to top-right)

Common Use Cases:

  1. Screenshare Preview at Bottom:

    SubAspectComponent(
      options: SubAspectComponentOptions(
        backgroundColor: Colors.black,
        children: [
          VideoCard(
            options: VideoCardOptions(
              videoStream: screenshareStream,
              participant: presenter,
              parameters: parameters,
            ),
          ),
        ],
        showControls: parameters.shared, // visible only when screensharing active
        containerHeightFraction: 0.3, // 30% of screen height
        containerWidthFraction: 0.5,  // 50% of screen width
        padding: EdgeInsets.all(8),
        containerDecoration: BoxDecoration(
          border: Border.all(color: Colors.blue, width: 2),
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    )
    
  2. Fixed-Height Control Bar:

    SubAspectComponent(
      options: SubAspectComponentOptions(
        backgroundColor: Colors.grey[900]!,
        children: [
          ControlButtonsComponent(
            options: ControlButtonsComponentOptions(
              buttons: allButtons,
              parameters: parameters,
            ),
          ),
        ],
        showControls: true,
        defaultFractionSub: 80.0, // 80 pixels fixed height
        alignment: Alignment.center,
      ),
    )
    
  3. Mini Video Player (Top-Right):

    SubAspectComponent(
      options: SubAspectComponentOptions(
        backgroundColor: Colors.black,
        children: [
          VideoCard(
            options: VideoCardOptions(
              videoStream: localStream,
              participant: localParticipant,
              parameters: parameters,
            ),
          ),
        ],
        showControls: true,
        defaultFractionSub: 0.2, // 20% of screen height
        containerWidthFraction: 0.25, // 25% of screen width
        wrapperBuilder: (context) {
          return Positioned(
            top: 16,
            right: 16,
            child: context.container,
          );
        },
        containerDecoration: BoxDecoration(
          borderRadius: BorderRadius.circular(12),
          boxShadow: [BoxShadow(color: Colors.black45, blurRadius: 6)],
        ),
      ),
    )
    
  4. Audio Participant Grid (Compact):

    SubAspectComponent(
      options: SubAspectComponentOptions(
        backgroundColor: Colors.transparent,
        children: [
          AudioGrid(
            options: AudioGridOptions(
              componentsToRender: audioCards,
            ),
          ),
        ],
        showControls: parameters.audioOnlyRoom,
        defaultFractionSub: 100.0, // 100 pixels for audio cards
        padding: EdgeInsets.symmetric(horizontal: 8),
      ),
    )
    

Override Integration: Integrates with MediasfuUICustomOverrides for global styling:

overrides: MediasfuUICustomOverrides(
  subAspectComponentOptions: ComponentOverride<SubAspectComponentOptions>(
    builder: (existingOptions) => SubAspectComponentOptions(
      backgroundColor: existingOptions.backgroundColor,
      children: existingOptions.children,
      showControls: existingOptions.showControls,
      defaultFractionSub: 0.25, // Always use 25% height
      containerWidthFraction: 0.4, // Always use 40% width
      containerDecoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.black87, Colors.grey[850]!],
        ),
        borderRadius: BorderRadius.circular(16),
      ),
      padding: EdgeInsets.all(12),
      margin: EdgeInsets.only(bottom: 16, left: 16),
    ),
  ),
),

Responsive Behavior:

  • Dimensions recalculate automatically on orientation change (via didChangeDependencies)
  • Width/height update immediately when fractions change (via didUpdateWidget)
  • Container collapses to zero height when showControls = false (smooth hide/show)
  • Fractional sizing adapts to different screen sizes (tablet, phone, desktop)

State Update Triggers:

  • showControls change → height recalculated (collapse or expand)
  • containerWidthFraction change → width recalculated
  • containerHeightFraction change → height recalculated
  • defaultFractionSub change → height recalculated (if containerHeightFraction null)
  • Screen rotation → all dimensions recalculated (didChangeDependencies)

Performance Notes:

  • Stateful widget (maintains _width and _height state)
  • setState() called only when dimensions change (not every frame)
  • Builder hooks called during every build (not cached)
  • Positioned widget prevents layout reflow (absolute positioning)
  • Visibility widget efficiently hides without removing from tree

Implementation Details:

  • Uses MediaQuery.of(context).size for screen dimensions
  • Clamps fractions to 0.0, 1.0 range to prevent invalid sizes
  • Checks mounted before calling setState() (prevents errors after dispose)
  • Stack uses clipBehavior from options (defaults to Clip.hardEdge)
  • Container dimensions default to full width if no fraction provided
  • Positioned always places container at bottom-left unless wrapperBuilder overrides

Typical Usage Context:

  • Secondary video area in video conferencing
  • Screenshare preview overlay
  • Control button panel at bottom
  • Mini participant video (picture-in-picture style)
  • Audio-only participant list (compact view)
Inheritance

Constructors

SubAspectComponent({Key? key, required SubAspectComponentOptions options})
const

Properties

hashCode int
The hash code for this object.
no setterinherited
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
options SubAspectComponentOptions
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<SubAspectComponent>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited