mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-06-26 17:56:28 +08:00
Merge pull request #55 from simpleclub-extended/intrinsics
Implement intrinsic sizing
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
## [0.6.8] - 2021-02-12 11:11:11
|
||||||
|
|
||||||
|
- Adds support for Flutter's `getMinIntrinsicWidth` (max, height, etc.), e.g. for `IntrinsicWidth`
|
||||||
|
and `IntrinsicHeight` usage.
|
||||||
|
- Renames `Rive.useIntrinsicSize` to `Rive.useArtboardSize` by deprecating the former. The
|
||||||
|
motivation for this is avoiding ambiguity with Flutter's intrinsics contract.
|
||||||
|
|
||||||
## [0.6.7] - 2021-01-23 11:11:02
|
## [0.6.7] - 2021-01-23 11:11:02
|
||||||
|
|
||||||
- Adds support for Rive.useIntrinsicSize to allow Rive widgets to be self sized by their artboard. Set useIntrinsicSize to false when you want the widget to try to occupy the entire space provided by the parent.
|
- Adds support for Rive.useIntrinsicSize to allow Rive widgets to be self sized by their artboard. Set useIntrinsicSize to false when you want the widget to try to occupy the entire space provided by the parent.
|
||||||
|
@ -7,16 +7,40 @@ import 'package:rive/src/runtime_artboard.dart';
|
|||||||
|
|
||||||
class Rive extends LeafRenderObjectWidget {
|
class Rive extends LeafRenderObjectWidget {
|
||||||
final Artboard artboard;
|
final Artboard artboard;
|
||||||
final bool useIntrinsicSize;
|
|
||||||
|
/// Determines whether to use the inherent size of the [artboard], i.e. the
|
||||||
|
/// absolute size defined by the artboard, or size the widget based on the
|
||||||
|
/// available constraints only (sized by parent).
|
||||||
|
///
|
||||||
|
/// Defaults to `false`, i.e. defaults to sizing based on the available
|
||||||
|
/// constraints instead of the artboard size.
|
||||||
|
///
|
||||||
|
/// When `true`, the artboard size is constrained by the parent constraints.
|
||||||
|
/// Using the artboard size has the benefit that the widget now has an
|
||||||
|
/// *intrinsic* size.
|
||||||
|
///
|
||||||
|
/// When `false`, the intrinsic size is `(0, 0)` because
|
||||||
|
/// there is no size intrinsically - it only comes from the parent
|
||||||
|
/// constraints. Consequently, if you intend to use the widget in the subtree
|
||||||
|
/// of an [IntrinsicWidth] or [IntrinsicHeight] widget or intend to directly
|
||||||
|
/// obtain the [RenderBox.getMinIntrinsicWidth] et al., you will want to set
|
||||||
|
/// this to `true`.
|
||||||
|
final bool useArtboardSize;
|
||||||
|
|
||||||
final BoxFit fit;
|
final BoxFit fit;
|
||||||
final Alignment alignment;
|
final Alignment alignment;
|
||||||
|
|
||||||
const Rive({
|
const Rive({
|
||||||
@required this.artboard,
|
@required
|
||||||
this.useIntrinsicSize = false,
|
this.artboard,
|
||||||
|
@Deprecated("Replaced by [useArtboardSize] in order to avoid confusion "
|
||||||
|
"with Flutter's intrinsics contract.")
|
||||||
|
bool useIntrinsicSize,
|
||||||
|
bool useArtboardSize = false,
|
||||||
this.fit = BoxFit.contain,
|
this.fit = BoxFit.contain,
|
||||||
this.alignment = Alignment.center,
|
this.alignment = Alignment.center,
|
||||||
});
|
}) : assert(useArtboardSize != null),
|
||||||
|
useArtboardSize = useIntrinsicSize ?? useArtboardSize;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
RenderObject createRenderObject(BuildContext context) {
|
RenderObject createRenderObject(BuildContext context) {
|
||||||
@ -24,9 +48,9 @@ class Rive extends LeafRenderObjectWidget {
|
|||||||
..artboard = artboard
|
..artboard = artboard
|
||||||
..fit = fit
|
..fit = fit
|
||||||
..alignment = alignment
|
..alignment = alignment
|
||||||
..intrinsicSize =
|
..artboardSize =
|
||||||
artboard == null ? Size.zero : Size(artboard.width, artboard.height)
|
artboard == null ? Size.zero : Size(artboard.width, artboard.height)
|
||||||
..useIntrinsicSize = useIntrinsicSize;
|
..useArtboardSize = useArtboardSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -36,9 +60,9 @@ class Rive extends LeafRenderObjectWidget {
|
|||||||
..artboard = artboard
|
..artboard = artboard
|
||||||
..fit = fit
|
..fit = fit
|
||||||
..alignment = alignment
|
..alignment = alignment
|
||||||
..intrinsicSize =
|
..artboardSize =
|
||||||
artboard == null ? Size.zero : Size(artboard.width, artboard.height)
|
artboard == null ? Size.zero : Size(artboard.width, artboard.height)
|
||||||
..useIntrinsicSize = useIntrinsicSize;
|
..useArtboardSize = useArtboardSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -49,7 +73,9 @@ class Rive extends LeafRenderObjectWidget {
|
|||||||
|
|
||||||
class RiveRenderObject extends RiveRenderBox {
|
class RiveRenderObject extends RiveRenderBox {
|
||||||
RuntimeArtboard _artboard;
|
RuntimeArtboard _artboard;
|
||||||
|
|
||||||
RuntimeArtboard get artboard => _artboard;
|
RuntimeArtboard get artboard => _artboard;
|
||||||
|
|
||||||
set artboard(Artboard value) {
|
set artboard(Artboard value) {
|
||||||
if (_artboard == value) {
|
if (_artboard == value) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
@ -10,32 +11,36 @@ abstract class RiveRenderBox extends RenderBox {
|
|||||||
final Stopwatch _stopwatch = Stopwatch();
|
final Stopwatch _stopwatch = Stopwatch();
|
||||||
BoxFit _fit;
|
BoxFit _fit;
|
||||||
Alignment _alignment;
|
Alignment _alignment;
|
||||||
bool _useIntrinsicSize = false;
|
bool _useArtboardSize = false;
|
||||||
|
|
||||||
bool get useIntrinsicSize => _useIntrinsicSize;
|
bool get useArtboardSize => _useArtboardSize;
|
||||||
set useIntrinsicSize(bool value) {
|
|
||||||
if (_useIntrinsicSize == value) {
|
set useArtboardSize(bool value) {
|
||||||
|
if (_useArtboardSize == value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_useIntrinsicSize = value;
|
_useArtboardSize = value;
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
markNeedsLayoutForSizedByParentChange();
|
markNeedsLayoutForSizedByParentChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Size _intrinsicSize;
|
Size _artboardSize;
|
||||||
Size get intrinsicSize => _intrinsicSize;
|
|
||||||
set intrinsicSize(Size value) {
|
Size get artboardSize => _artboardSize;
|
||||||
if (_intrinsicSize == value) {
|
|
||||||
|
set artboardSize(Size value) {
|
||||||
|
if (_artboardSize == value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_intrinsicSize = value;
|
_artboardSize = value;
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
markNeedsLayoutForSizedByParentChange();
|
markNeedsLayoutForSizedByParentChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxFit get fit => _fit;
|
BoxFit get fit => _fit;
|
||||||
|
|
||||||
set fit(BoxFit value) {
|
set fit(BoxFit value) {
|
||||||
if (value != _fit) {
|
if (value != _fit) {
|
||||||
_fit = value;
|
_fit = value;
|
||||||
@ -44,6 +49,7 @@ abstract class RiveRenderBox extends RenderBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Alignment get alignment => _alignment;
|
Alignment get alignment => _alignment;
|
||||||
|
|
||||||
set alignment(Alignment value) {
|
set alignment(Alignment value) {
|
||||||
if (value != _alignment) {
|
if (value != _alignment) {
|
||||||
_alignment = value;
|
_alignment = value;
|
||||||
@ -52,24 +58,94 @@ abstract class RiveRenderBox extends RenderBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get sizedByParent => !_useIntrinsicSize || _intrinsicSize == null;
|
bool get sizedByParent => !useArtboardSize || artboardSize == null;
|
||||||
|
|
||||||
@override
|
/// Finds the intrinsic size for the rive render box given the [constraints]
|
||||||
void performLayout() {
|
/// and [sizedByParent].
|
||||||
if (!sizedByParent) {
|
///
|
||||||
size = constraints
|
/// The difference between the intrinsic size returned here and the size we
|
||||||
.constrainSizeAndAttemptToPreserveAspectRatio(_intrinsicSize);
|
/// use for [performResize] is that the intrinsics contract does not allow
|
||||||
|
/// infinite sizes, i.e. we cannot return biggest constraints.
|
||||||
|
/// Consequently, the smallest constraint is returned in case we are
|
||||||
|
/// [sizedByParent].
|
||||||
|
Size _intrinsicSizeForConstraints(BoxConstraints constraints) {
|
||||||
|
if (sizedByParent) {
|
||||||
|
return constraints.smallest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return constraints
|
||||||
|
.constrainSizeAndAttemptToPreserveAspectRatio(artboardSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool hitTestSelf(Offset screenOffset) => true;
|
double computeMinIntrinsicWidth(double height) {
|
||||||
|
assert(height >= 0.0);
|
||||||
|
// If not sized by parent, this returns the constrained (trying to preserve
|
||||||
|
// aspect ratio) artboard size.
|
||||||
|
// If sized by parent, this returns 0 (because an infinite width does not
|
||||||
|
// make sense as an intrinsic width and is therefore not allowed).
|
||||||
|
return _intrinsicSizeForConstraints(
|
||||||
|
BoxConstraints.tightForFinite(height: height))
|
||||||
|
.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMaxIntrinsicWidth(double height) {
|
||||||
|
assert(height >= 0.0);
|
||||||
|
// This is equivalent to the min intrinsic width because we cannot provide
|
||||||
|
// any greater intrinsic width beyond which increasing the width never
|
||||||
|
// decreases the preferred height.
|
||||||
|
// When we have an artboard size, the intrinsic min and max width are
|
||||||
|
// obviously equivalent and if sized by parent, we can also only return the
|
||||||
|
// smallest width constraint (which is 0 in the case of intrinsic width).
|
||||||
|
return _intrinsicSizeForConstraints(
|
||||||
|
BoxConstraints.tightForFinite(height: height))
|
||||||
|
.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMinIntrinsicHeight(double width) {
|
||||||
|
assert(width >= 0.0);
|
||||||
|
// If not sized by parent, this returns the constrained (trying to preserve
|
||||||
|
// aspect ratio) artboard size.
|
||||||
|
// If sized by parent, this returns 0 (because an infinite height does not
|
||||||
|
// make sense as an intrinsic height and is therefore not allowed).
|
||||||
|
return _intrinsicSizeForConstraints(
|
||||||
|
BoxConstraints.tightForFinite(width: width))
|
||||||
|
.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMaxIntrinsicHeight(double width) {
|
||||||
|
assert(width >= 0.0);
|
||||||
|
// This is equivalent to the min intrinsic height because we cannot provide
|
||||||
|
// any greater intrinsic height beyond which increasing the height never
|
||||||
|
// decreases the preferred width.
|
||||||
|
// When we have an artboard size, the intrinsic min and max height are
|
||||||
|
// obviously equivalent and if sized by parent, we can also only return the
|
||||||
|
// smallest height constraint (which is 0 in the case of intrinsic height).
|
||||||
|
return _intrinsicSizeForConstraints(
|
||||||
|
BoxConstraints.tightForFinite(width: width))
|
||||||
|
.height;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void performResize() {
|
void performResize() {
|
||||||
size = constraints.biggest;
|
size = constraints.biggest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void performLayout() {
|
||||||
|
if (!sizedByParent) {
|
||||||
|
// We can use the intrinsic size here because the intrinsic size matches
|
||||||
|
// the constrained artboard size when not sized by parent.
|
||||||
|
size = _intrinsicSizeForConstraints(constraints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool hitTestSelf(Offset screenOffset) => true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void detach() {
|
void detach() {
|
||||||
_stopwatch.stop();
|
_stopwatch.stop();
|
||||||
@ -78,18 +154,21 @@ abstract class RiveRenderBox extends RenderBox {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void attach(PipelineOwner owner) {
|
void attach(PipelineOwner owner) {
|
||||||
_stopwatch.start();
|
|
||||||
super.attach(owner);
|
super.attach(owner);
|
||||||
|
_stopwatch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the Axis Aligned Bounding Box that encompasses the world space scene
|
/// Get the Axis Aligned Bounding Box that encompasses the world space scene
|
||||||
AABB get aabb;
|
AABB get aabb;
|
||||||
|
|
||||||
void draw(Canvas canvas, Mat2D viewTransform);
|
void draw(Canvas canvas, Mat2D viewTransform);
|
||||||
|
|
||||||
void beforeDraw(Canvas canvas, Offset offset) {}
|
void beforeDraw(Canvas canvas, Offset offset) {}
|
||||||
|
|
||||||
void afterDraw(Canvas canvas, Offset offset) {}
|
void afterDraw(Canvas canvas, Offset offset) {}
|
||||||
|
|
||||||
double _elapsedSeconds = 0;
|
double _elapsedSeconds = 0;
|
||||||
|
|
||||||
void _frameCallback(Duration duration) {
|
void _frameCallback(Duration duration) {
|
||||||
_elapsedSeconds = _stopwatch.elapsedTicks / _stopwatch.frequency;
|
_elapsedSeconds = _stopwatch.elapsedTicks / _stopwatch.frequency;
|
||||||
_stopwatch.reset();
|
_stopwatch.reset();
|
||||||
@ -98,6 +177,7 @@ abstract class RiveRenderBox extends RenderBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int _frameCallbackId;
|
int _frameCallbackId;
|
||||||
|
|
||||||
void scheduleRepaint() {
|
void scheduleRepaint() {
|
||||||
if (_frameCallbackId != null) {
|
if (_frameCallbackId != null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: rive
|
name: rive
|
||||||
description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
|
description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
|
||||||
version: 0.6.7
|
version: 0.6.8
|
||||||
repository: https://github.com/rive-app/rive-flutter
|
repository: https://github.com/rive-app/rive-flutter
|
||||||
homepage: https://rive.app
|
homepage: https://rive.app
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user