Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 44 additions & 19 deletions docs/widgets/positioned.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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. |

<Note>
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.
</Note>

## Example
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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'),
)
```
5 changes: 1 addition & 4 deletions examples/movie_app/stac/onboarding_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
77 changes: 77 additions & 0 deletions packages/stac_core/lib/widgets/positioned/stac_positioned.dart
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down