PrimaryLayoutKt

Added in 1.3.0-alpha08

public final class PrimaryLayoutKt


Summary

Public methods

static final @NonNull LayoutElementBuilders.LayoutElement

ProtoLayout Material3 full screen layout that represents a suggested Material3 layout style that is responsive and takes care of the elements placement, together with the recommended margin and padding applied.

Public methods

public static final @NonNull LayoutElementBuilders.LayoutElement primaryLayout(
    @NonNull MaterialScope receiver,
    @ExtensionFunctionType @NonNull Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> mainSlot,
    @ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> titleSlot,
    @ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> bottomSlot,
    @ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> labelForBottomSlot,
    ModifiersBuilders.Clickable onClick,
    @NonNull PrimaryLayoutMargins margins
)

ProtoLayout Material3 full screen layout that represents a suggested Material3 layout style that is responsive and takes care of the elements placement, together with the recommended margin and padding applied.

This layout is meant to occupy the whole screen, so nothing else should be added on top of it.

On the top, there is an icon that will be automatically placed by the system, followed by the optional title slot. The icon slot needs to be reserved for the whole ProtoLayout Layout and no other content should be added at the top of the screen as it will be overlapped with the system placed icon.

At the bottom, there is an optional fixed slot for either {@link EdgeButton} as a main action or small non tappable content.

The middle of the layout is main content, that will fill the available space. For the best results across different screen sizes, it's recommended that this content's dimension are also DimensionBuilders.expand or DimensionBuilders.weight. Additional content in the main one can be added after a 225dp breakpoint.

import androidx.wear.protolayout.LayoutElementBuilders
import androidx.wear.protolayout.LayoutElementBuilders.Box
import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
import androidx.wear.protolayout.ModifiersBuilders
import androidx.wear.protolayout.material3.PrimaryLayoutMargins.Companion.MAX_PRIMARY_LAYOUT_MARGIN
import androidx.wear.protolayout.material3.button
import androidx.wear.protolayout.material3.buttonGroup
import androidx.wear.protolayout.material3.icon
import androidx.wear.protolayout.material3.iconEdgeButton
import androidx.wear.protolayout.material3.materialScope
import androidx.wear.protolayout.material3.primaryLayout
import androidx.wear.protolayout.material3.text
import androidx.wear.protolayout.modifiers.LayoutModifier
import androidx.wear.protolayout.modifiers.clickable
import androidx.wear.protolayout.modifiers.contentDescription
import androidx.wear.protolayout.types.layoutString

materialScope(context, deviceConfiguration) {
        primaryLayout(
            titleSlot = { text("App title".layoutString) },
            mainSlot = {
                buttonGroup {
                    // To be populated with proper components
                    buttonGroupItem {
                        LayoutElementBuilders.Box.Builder()
                            .setModifiers(
                                ModifiersBuilders.Modifiers.Builder()
                                    .setBackground(
                                        ModifiersBuilders.Background.Builder()
                                            .setCorner(shapes.small)
                                            .build()
                                    )
                                    .build()
                            )
                            .build()
                    }
                }
            },
            // Adjust margins as the corner of the inner content is on the square side.
            margins = MAX_PRIMARY_LAYOUT_MARGIN,
            bottomSlot = {
                iconEdgeButton(
                    onClick = clickable,
                    modifier = LayoutModifier.contentDescription("Description")
                ) {
                    icon("id")
                }
            }
        )
    }
import androidx.wear.protolayout.DimensionBuilders.expand
import androidx.wear.protolayout.material3.backgroundImage
import androidx.wear.protolayout.material3.card
import androidx.wear.protolayout.material3.materialScope
import androidx.wear.protolayout.material3.primaryLayout
import androidx.wear.protolayout.material3.text
import androidx.wear.protolayout.modifiers.LayoutModifier
import androidx.wear.protolayout.modifiers.clickable
import androidx.wear.protolayout.modifiers.contentDescription
import androidx.wear.protolayout.types.layoutString

materialScope(context, deviceConfiguration) {
        primaryLayout(
            mainSlot = {
                card(
                    onClick = clickable,
                    modifier =
                        LayoutModifier.contentDescription("Card with image background")
                            .clickable(id = "card"),
                    width = expand(),
                    height = expand(),
                    backgroundContent = { backgroundImage(protoLayoutResourceId = "id") }
                ) {
                    text("Content of the Card!".layoutString)
                }
            }
        )
    }
import androidx.wear.protolayout.DimensionBuilders.expand
import androidx.wear.protolayout.material3.button
import androidx.wear.protolayout.material3.buttonGroup
import androidx.wear.protolayout.material3.icon
import androidx.wear.protolayout.material3.iconButton
import androidx.wear.protolayout.material3.materialScope
import androidx.wear.protolayout.material3.primaryLayout
import androidx.wear.protolayout.material3.text
import androidx.wear.protolayout.material3.textButton
import androidx.wear.protolayout.modifiers.LayoutModifier
import androidx.wear.protolayout.modifiers.clickable
import androidx.wear.protolayout.modifiers.contentDescription
import androidx.wear.protolayout.types.layoutString

materialScope(context, deviceConfiguration) {
        primaryLayout(
            mainSlot = {
                buttonGroup {
                    buttonGroupItem {
                        iconButton(
                            onClick = clickable,
                            modifier =
                                LayoutModifier.contentDescription(
                                    "Big button with image background"
                                ),
                            width = expand(),
                            height = expand(),
                            iconContent = { icon("id1") }
                        )
                    }
                    buttonGroupItem {
                        iconButton(
                            onClick = clickable,
                            modifier =
                                LayoutModifier.contentDescription(
                                    "Big button with image background"
                                ),
                            width = expand(),
                            height = expand(),
                            shape = shapes.large,
                            iconContent = { icon("id2") }
                        )
                    }
                    buttonGroupItem {
                        textButton(
                            onClick = clickable,
                            modifier =
                                LayoutModifier.contentDescription(
                                    "Big button with image background"
                                ),
                            width = expand(),
                            height = expand(),
                            shape = shapes.large,
                            labelContent = { text("Dec".layoutString) }
                        )
                    }
                }
            }
        )
    }
import androidx.wear.protolayout.DimensionBuilders.expand
import androidx.wear.protolayout.material3.CardDefaults.filledVariantCardColors
import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.filledTonalProgressIndicatorColors
import androidx.wear.protolayout.material3.GraphicDataCardStyle.Companion.largeGraphicDataCardStyle
import androidx.wear.protolayout.material3.graphicDataCard
import androidx.wear.protolayout.material3.icon
import androidx.wear.protolayout.material3.materialScope
import androidx.wear.protolayout.material3.primaryLayout
import androidx.wear.protolayout.material3.segmentedCircularProgressIndicator
import androidx.wear.protolayout.material3.text
import androidx.wear.protolayout.modifiers.LayoutModifier
import androidx.wear.protolayout.modifiers.clickable
import androidx.wear.protolayout.modifiers.contentDescription
import androidx.wear.protolayout.types.layoutString

materialScope(context, deviceConfiguration) {
        primaryLayout(
            mainSlot = {
                graphicDataCard(
                    onClick = clickable,
                    modifier = LayoutModifier.contentDescription("Data Card with graphic"),
                    height = expand(),
                    colors = filledVariantCardColors(),
                    style = largeGraphicDataCardStyle(),
                    title = { text("1,234".layoutString) },
                    content = { icon("steps") },
                    graphic = {
                        segmentedCircularProgressIndicator(
                            segmentCount = 5,
                            staticProgress = 0.5F,
                            colors = filledTonalProgressIndicatorColors(),
                        )
                    },
                )
            }
        )
    }
Parameters
@ExtensionFunctionType @NonNull Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> mainSlot

The main, central content for this layout. It's recommended for this content to fill the available width and height for the best result across different screen size. This layout places proper padding to prevent content from being cropped by the screen. Note that depending on the corner shapes and different elements on the screen, there might be a need to change padding on some of the elements in this slot. The content passed here can also have an additional content value added to it, after 225dp breakpoint. Some of the examples of content that can be passed in here are: * buttonGroup with buttons or cards * two [buttonGroup * Expanded card

@ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> titleSlot

The app title in the top slot, just below the icon. This should be one line of text with Typography.TITLE_SMALL typography, describing the main purpose of this layout. Title is an optional slot which can be omitted to make space for other elements. Defaults to ColorScheme.onBackground color.

@ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> bottomSlot

The content for bottom slot in this layout, that will be anchored to the bottom edge of the screen. This should be either a small non tappable content such as Text with optional label for it or tappable main action with textEdgeButton or iconEdgeButton which is designed to have its bottom following the screen's curvature. This bottom slot is optional, if unset the main content will expand more towards the edge of the screen.

@ExtensionFunctionType Function1<@NonNull MaterialScope, @NonNull LayoutElementBuilders.LayoutElement> labelForBottomSlot

The label displayed just above the bottomSlot. Default will be one line of text with Typography.TITLE_SMALL typography, ColorScheme.onSurface color that should contain additional description of this layout. When the bottomSlot is not provided or it an edge button, the given label will be ignored.

ModifiersBuilders.Clickable onClick

The clickable action for whole layout. If any area (outside of other added tappable components) is clicked, it will fire the associated action.

@NonNull PrimaryLayoutMargins margins

The customized outer margin that will be applied as following: * start and end would be applied as a side margins on mainSlot * bottom would be applied as a bottom margin when bottomSlot is not present.

It is highly recommended to use provided constants for these margins - DEFAULT_PRIMARY_LAYOUT_MARGIN, MIN_PRIMARY_LAYOUT_MARGIN, MID_PRIMARY_LAYOUT_MARGIN or MAX_PRIMARY_LAYOUT_MARGIN, depending on inner content and its corners shape. If providing custom numbers by customizedPrimaryLayoutMargin, it is a requirement for those to be percentages of the screen width and height.