ControlButtonsComponentTouch class

A stateless widget rendering touch-optimized control buttons with extensive customization.

Most comprehensive control button variant designed for mobile/tablet touch interfaces. Provides per-button styling, state color system, accessibility support, and six builder hooks for maximum flexibility.

Rendering Logic:

  1. If showAspect=false → returns invisible Container
  2. Filters buttons: only renders buttons where show=true
  3. Builds button widgets using _buildButton (applies all styling/state logic)
  4. Inserts gap widgets between buttons (if gap > 0)
  5. Wraps in Row (horizontal) or Column (vertical)
  6. Wraps in Container with alignment (position/location)
  7. Applies builder hooks at each layer

Layout Structure:

Visibility (showAspect)
  └─ Container (containerBuilder)
     └─ Row/Column (buttonsBuilder)
        ├─ [IF gap > 0] SizedBox (spacing)
        ├─ Semantics (buttonBuilder)
        │  └─ GestureDetector (onTap → button.onPress)
        │     └─ Container (button background, state colors)
        │        └─ Row/Column (buttonContentBuilder)
        │           ├─ [Icon] (iconBuilder)
        │           ├─ [IF contentGap > 0] SizedBox
        │           └─ [Text] (labelBuilder)
        ├─ [IF gap > 0] SizedBox
        ├─ [Next button] ...
        └─ ...

Button State Logic: For each ButtonTouch, determines background color:

  1. If disabled=true → uses buttonBackgroundColors.disabledColor or button.backgroundColor'disabled'
  2. If active=true → uses buttonBackgroundColors.activeColor or button.backgroundColor'active'
  3. Else → uses buttonBackgroundColors.defaultColor or button.backgroundColor'default' Icon color:
  4. If active=true → uses button.activeColor or global activeIconColor
  5. Else → uses button.inActiveColor or global inactiveIconColor Icon widget:
  6. If active=true → uses button.alternateIconWidget or alternateIconComponent or Icon(button.alternateIcon)
  7. Else → uses button.iconWidget or iconComponent or Icon(button.icon)

Builder Hook Priorities:

  1. Per-button builders (button.contentBuilder, button.iconBuilder, etc.) override global builders
  2. Global builders (options.buttonBuilder, options.iconBuilder, etc.) applied if per-button not set
  3. Builder hooks receive context objects with computed state (isActive, etc.)

Touch Target Sizing:

  • Default buttonConstraints: BoxConstraints(minWidth: 48, minHeight: 48) recommended
  • Meets WCAG 2.1 Level AA touch target guideline (44x44 minimum)
  • Icon sizes typically 24-32 for touch (vs 16-20 for mouse)

Accessibility Features:

  • semanticsLabel on each button for screen readers
  • Semantics widget wraps each button with label
  • State announced: "Button, label, active/inactive"
  • Disabled buttons marked non-interactive

Common Use Cases:

  1. Mobile Bottom Bar:

    ControlButtonsComponentTouch(
      options: ControlButtonsComponentTouchOptions(
        buttons: [
          ButtonTouch(name: 'Mic', icon: Icons.mic_off, alternateIcon: Icons.mic, onPress: toggleMic, active: isMicOn, semanticsLabel: 'Toggle microphone'),
          ButtonTouch(name: 'Video', icon: Icons.videocam_off, alternateIcon: Icons.videocam, onPress: toggleVideo, active: isVideoOn, semanticsLabel: 'Toggle camera'),
          ButtonTouch(name: 'Share', icon: Icons.screen_share, onPress: shareScreen, semanticsLabel: 'Share screen'),
          ButtonTouch(name: 'More', icon: Icons.more_horiz, onPress: openMenu, semanticsLabel: 'More options'),
        ],
        direction: 'horizontal',
        position: 'center',
        location: 'bottom',
        gap: 16,
        containerDecoration: BoxDecoration(color: Colors.black87, borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
        buttonConstraints: BoxConstraints(minWidth: 64, minHeight: 64),
        iconSize: 28,
      ),
    )
    
  2. Vertical Sidebar (Tablet):

    ControlButtonsComponentTouch(
      options: ControlButtonsComponentTouchOptions(
        buttons: quickActions,
        direction: 'vertical',
        position: 'right',
        location: 'center',
        gap: 12,
        buttonBackgroundColors: ControlButtonsTouchStateColors(
          defaultColor: Colors.grey[800],
          activeColor: Colors.blue,
          pressedColor: Colors.blue[700],
        ),
      ),
    )
    
  3. State-Aware Recording Button:

    ControlButtonsComponentTouch(
      options: ControlButtonsComponentTouchOptions(
        buttons: [
          ButtonTouch(
            name: isRecording ? 'Stop' : 'Record',
            icon: isRecording ? Icons.stop : Icons.fiber_manual_record,
            onPress: isRecording ? stopRecording : startRecording,
            active: isRecording,
            backgroundColor: {
              'default': Colors.grey[800]!,
              'active': Colors.red,
              'pressed': Colors.red[700]!,
            },
            semanticsLabel: isRecording ? 'Stop recording' : 'Start recording',
          ),
        ],
      ),
    )
    
  4. Custom Button with Badge:

    ControlButtonsComponentTouch(
      options: ControlButtonsComponentTouchOptions(
        buttons: [
          ButtonTouch(
            name: 'Messages',
            icon: Icons.message,
            onPress: openMessages,
            buttonBuilder: (context, defaultButton) {
              return Badge(
                label: Text('3'),
                child: defaultButton,
              );
            },
          ),
        ],
      ),
    )
    

Override Integration: Integrates with MediasfuUICustomOverrides for global styling:

overrides: MediasfuUICustomOverrides(
  controlButtonsTouchOptions: ComponentOverride<ControlButtonsComponentTouchOptions>(
    builder: (existingOptions) => ControlButtonsComponentTouchOptions(
      buttons: existingOptions.buttons,
      direction: existingOptions.direction,
      position: 'center',
      location: 'bottom',
      gap: 20,
      containerDecoration: BoxDecoration(
        gradient: LinearGradient(colors: [Colors.black, Colors.grey[900]!]),
        borderRadius: BorderRadius.circular(32),
        boxShadow: [BoxShadow(color: Colors.black38, blurRadius: 12)],
      ),
      buttonBackgroundColors: ControlButtonsTouchStateColors(
        defaultColor: Colors.grey[800],
        activeColor: Colors.green,
        disabledColor: Colors.grey[700],
      ),
      iconSize: 32,
      textStyle: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
    ),
  ),
),

Performance Notes:

  • Filters buttons once per build (buttons.where)
  • Gap widgets only inserted if gap > 0 (avoids empty SizedBox)
  • Builder hooks called once per button per build
  • Semantics labels important for accessibility but don't affect render performance

Implementation Details:

  • Position/location props map to Alignment: ('left', 'top') → Alignment.topLeft
  • Direction maps to Axis: 'horizontal' → Axis.horizontal, 'vertical' → Axis.vertical
  • MainAxisAlignment computed from position (horizontal) or location (vertical)
  • Per-button props override global props (checked via ?? operator)
  • State color resolution: per-button.backgroundColor → global.buttonBackgroundColors → fallback colors
Inheritance

Constructors

ControlButtonsComponentTouch({Key? key, required ControlButtonsComponentTouchOptions 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 ControlButtonsComponentTouchOptions
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

build(BuildContext context) Widget
Describes the part of the user interface represented by this widget.
override
createElement() StatelessElement
Creates a StatelessElement to manage this widget's location in the tree.
inherited
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