AdaptiveMasterDetail class

List and detail side by side when there is room, list alone when there is not.

This is the iPad split view and the tablet two-pane layout: below ScreenSize.compact only master is built and selecting a row is expected to push a page; from ScreenSize.medium up, detail fills the pane next to it and no navigation happens at all.

AdaptiveMasterDetail(
  master: ConversationList(onSelect: _select),
  detail: selected == null ? null : ConversationView(selected!),
  placeholder: const EmptyConversationState(),
)

The selection handler has to know which of the two modes is live, since pushing a page while the detail pane is visible would cover the pane it just filled. Ask isSplit:

void _select(Conversation c) {
  setState(() => selected = c);
  if (!AdaptiveMasterDetail.isSplit(context)) {
    Navigator.of(context).push(adaptivePageRoute(ConversationView(c)));
  }
}

Width buys a second pane, not larger type

The whole point of the layout is that a wide window shows two things at once instead of one thing blown up. Text inside either pane keeps the size it has on a phone — see AdaptiveTypography.

Measures its box, not the window

The decision comes from a LayoutBuilder, so the layout stays correct when it is itself inside a pane: an iPad in Slide Over, or a window the user dragged to a third of the screen, gets the single-pane treatment it should.

Inheritance

Constructors

AdaptiveMasterDetail({Key? key, required Widget master, Widget? detail, Widget? placeholder, double? masterWidth})
const

Properties

detail → Widget?
The detail pane, or null when nothing is selected.
final
hashCode → int
The hash code for this object.
no setterinherited
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
master → Widget
The list pane. Always built, at every size.
final
masterWidth → double?
Width of the list pane, in logical pixels.
final
placeholder → Widget?
Shown in the detail pane while detail is null.
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

Static Methods

isSplit(BuildContext context) → bool
Whether a window of this size shows both panes at once.