diff --git a/docs/widgets/positioned.mdx b/docs/widgets/positioned.mdx index 2e4747939..c9814c487 100644 --- a/docs/widgets/positioned.mdx +++ b/docs/widgets/positioned.mdx @@ -3,23 +3,28 @@ title: "Positioned" description: "Documentation for Positioned" --- -The Stac Positioned allows you to build a Flutter positioned widget using JSON. -To know more about the positioned widget in Flutter, refer to the [official documentation](https://api.flutter.dev/flutter/widgets/Positioned-class.html). +The Stac Positioned widget controls where a child of a [Stack](https://api.flutter.dev/flutter/widgets/Stack-class.html) is positioned. It corresponds to Flutter's Positioned widget and allows precise positioning using coordinates and optional sizing constraints. Use it with JSON to declare positioned children inside a Stack. + +To learn more about the Positioned widget in Flutter, see the [official documentation](https://api.flutter.dev/flutter/widgets/Positioned-class.html). + +## Positioning constraints + +Only **two of the three** horizontal values (`left`, `right`, `width`) may be set; at least one must be omitted or null. Similarly, only **two of the three** vertical values (`top`, `bottom`, `height`) may be set; at least one must be omitted or null. ## Properties | Property | Type | Description | |----------|--------------|--------------------------------------------------| -| left | `double` | The distance from the left edge of the parent. | -| top | `double` | The distance from the top edge of the parent. | -| right | `double` | The distance from the right edge of the parent. | -| bottom | `double` | The distance from the bottom edge of the parent. | -| width | `double` | The width of the child. | -| height | `double` | The height of the child. | -| child | `StacWidget` | The widget to display inside the positioned. | +| left | `double?` | The distance from the left edge of the stack. | +| top | `double?` | The distance from the top edge of the stack. | +| right | `double?` | The distance from the right edge of the stack. | +| bottom | `double?` | The distance from the bottom edge of the stack. | +| width | `double?` | The width of the positioned child. | +| height | `double?` | The height of the positioned child. | +| child | `StacWidget` | The widget to position within the stack. | -The Dart API also supports named constructors like `StacPositioned.fill()`, `StacPositioned.fromRect()`, and `StacPositioned.directional()`, but these are not available in JSON format. +The Dart API also supports named constructors: `StacPositioned.fill()`, `StacPositioned.fromRect()`, `StacPositioned.fromRelativeRect()`, and `StacPositioned.directional()`. These are not available in JSON format. ## Example @@ -56,6 +61,8 @@ The following named constructors are available in Dart but not in JSON: ### `StacPositioned.fill()` +Creates a positioned widget with `left`, `top`, `right`, and `bottom` defaulting to `0.0`, so the child fills the stack unless overridden. + ```dart StacPositioned.fill( left: 10, @@ -66,8 +73,35 @@ StacPositioned.fill( ) ``` +### `StacPositioned.fromRect()` + +Creates a positioned widget from a `StacRect`, setting `left`, `top`, `width`, and `height`. `right` and `bottom` are set to null. + +```dart +StacPositioned.fromRect( + rect: StacRect(left: 10, top: 20, width: 100, height: 50), + child: StacText(data: 'From rect'), +) +``` + +### `StacPositioned.fromRelativeRect()` + +Creates a positioned widget from relative edges: `left`, `top`, `right`, and `bottom` are required; `width` and `height` are null. + +```dart +StacPositioned.fromRelativeRect( + left: 10, + top: 20, + right: 30, + bottom: 40, + child: StacText(data: 'Relative rect'), +) +``` + ### `StacPositioned.directional()` +Creates a positioned widget using `start` and `end` instead of `left` and `right`. The mapping depends on `textDirection`: for LTR, `start` → `left` and `end` → `right`; for RTL, the opposite. Only two of `start`, `end`, and `width` may be set; only two of `top`, `bottom`, and `height` may be set. + ```dart StacPositioned.directional( textDirection: StacTextDirection.ltr, @@ -78,12 +112,3 @@ StacPositioned.directional( child: StacText(data: 'Directional positioning'), ) ``` - -### `StacPositioned.fromRect()` - -```dart -StacPositioned.fromRect( - rect: StacRect(left: 10, top: 20, width: 100, height: 50), - child: StacText(data: 'From rect'), -) -``` diff --git a/examples/movie_app/stac/onboarding_screen.dart b/examples/movie_app/stac/onboarding_screen.dart index ada942fc5..ae11dbcdf 100644 --- a/examples/movie_app/stac/onboarding_screen.dart +++ b/examples/movie_app/stac/onboarding_screen.dart @@ -13,10 +13,7 @@ StacWidget onboardingScreen() { height: double.maxFinite, fit: StacBoxFit.cover, ), - StacPositioned( - left: 0, - right: 0, - bottom: 0, + StacPositioned.fill( child: StacContainer( width: double.maxFinite, height: 500, diff --git a/packages/stac/lib/src/parsers/widgets/stac_positioned/stac_positioned_parser.dart b/packages/stac/lib/src/parsers/widgets/stac_positioned/stac_positioned_parser.dart index dfcb23b90..ded5a7ec7 100644 --- a/packages/stac/lib/src/parsers/widgets/stac_positioned/stac_positioned_parser.dart +++ b/packages/stac/lib/src/parsers/widgets/stac_positioned/stac_positioned_parser.dart @@ -1,4 +1,4 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:stac/src/parsers/core/stac_widget_parser.dart'; import 'package:stac_core/stac_core.dart'; import 'package:stac_framework/stac_framework.dart'; diff --git a/packages/stac_core/lib/widgets/positioned/stac_positioned.dart b/packages/stac_core/lib/widgets/positioned/stac_positioned.dart index 423c4e3ca..3475d9f6f 100644 --- a/packages/stac_core/lib/widgets/positioned/stac_positioned.dart +++ b/packages/stac_core/lib/widgets/positioned/stac_positioned.dart @@ -1,7 +1,9 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:stac_core/core/converters/double_converter.dart'; import 'package:stac_core/core/stac_widget.dart'; +import 'package:stac_core/foundation/geometry/stac_rect/stac_rect.dart'; import 'package:stac_core/foundation/specifications/widget_type.dart'; +import 'package:stac_core/foundation/text/stac_text_types.dart'; part 'stac_positioned.g.dart'; @@ -36,6 +38,10 @@ part 'stac_positioned.g.dart'; @JsonSerializable() class StacPositioned extends StacWidget { /// Creates a positioned widget with optional positioning and sizing. + /// + /// Only two of the three horizontal values ([left], [right], [width]) may be + /// set; at least one must be null. Similarly, only two of the three vertical + /// values ([top], [bottom], [height]) may be set; at least one must be null. const StacPositioned({ this.left, this.top, @@ -46,6 +52,77 @@ class StacPositioned extends StacWidget { required this.child, }); + /// Creates a StacPositioned object with the values from the given [StacRect]. + /// + /// This sets the [left], [top], [width], and [height] properties + /// from the given [StacRect]. The [right] and [bottom] properties are + /// set to null. + StacPositioned.fromRect({required StacRect rect, required this.child}) + : left = rect.left, + top = rect.top, + width = rect.width, + height = rect.height, + right = null, + bottom = null; + + /// Creates a StacPositioned object with the values from the given relative rectangle. + /// + /// This sets the [left], [top], [right], and [bottom] properties from the + /// given values. The [height] and [width] properties are set to null. + const StacPositioned.fromRelativeRect({ + required this.left, + required this.top, + required this.right, + required this.bottom, + required this.child, + }) : width = null, + height = null; + + /// Creates a StacPositioned object with [left], [top], [right], and [bottom] set + /// to 0.0 unless a value for them is passed. + const StacPositioned.fill({ + this.left = 0.0, + this.top = 0.0, + this.right = 0.0, + this.bottom = 0.0, + required this.child, + }) : width = null, + height = null; + + /// Creates a widget that controls where a child of a [Stack] is positioned. + /// + /// Only two of the three horizontal values (`start`, `end`, and [width]) may + /// be set; at least one must be null. Only two of the three vertical values + /// ([top], [bottom], and [height]) may be set; at least one must be null. + /// + /// If [textDirection] is [StacTextDirection.rtl], then `start` is used for + /// [right] and `end` for [left]. If [textDirection] is [StacTextDirection.ltr], + /// then `start` is used for [left] and `end` for [right]. + factory StacPositioned.directional({ + required StacTextDirection textDirection, + double? start, + double? top, + double? end, + double? bottom, + double? width, + double? height, + required StacWidget child, + }) { + final (double? left, double? right) = switch (textDirection) { + StacTextDirection.rtl => (end, start), + StacTextDirection.ltr => (start, end), + }; + return StacPositioned( + left: left, + top: top, + right: right, + bottom: bottom, + width: width, + height: height, + child: child, + ); + } + /// The distance from the left edge of the stack. @DoubleConverter() final double? left;