Skip to content

Instantly share code, notes, and snippets.

@jmolins
Created July 4, 2018 19:41
Show Gist options
  • Save jmolins/af52f0a8f33b409947259e2655eb0808 to your computer and use it in GitHub Desktop.
Save jmolins/af52f0a8f33b409947259e2655eb0808 to your computer and use it in GitHub Desktop.
BaselineBox complete, widget and example
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart';
void main() => runApp(new BaselineExampleApp());
class BaselineExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Center(
child: Container(
height: 200.0,
width: 220.0,
color: Colors.green,
child: Baseline(
baseline: 0.0,
baselineType: TextBaseline.alphabetic,
child: BaselineBox(
baseline: 30.0,
//fromTop: true,
child: Container(
color: Colors.red,
height: 100.0,
width: 100.0,
),
),
),
),
),
),
);
}
}
/// A widget that sets a baseline based on the distance in logical pixels to
/// its bottom or to its top.
///
/// By default, when no values are provided, the baseline coincides with the
/// bottom of the widget, as this is de default behavior for widgets without a
/// baseline. When the param `baseline` has a value, it represents the offset
/// from the bottom.
///
/// If `fromTop` is true, the baseline is the offset from the top of the widget.
///
/// ```dart
/// Baselined(
/// baseline: 15.0,
/// child: Container(
/// padding: 20.0,
/// child: Text('The baseline is now 5.0 below this text widget'),
/// )
/// ```
///
/// The baseline is set regardless of the [TextBaseline] type, meaning that
/// when the baseline for this widget is queried from the parent, the same
/// baseline will be returned regardless of the [TextBaseline] type queried.
///
/// See also:
///
/// * [Baseline], a widget that positions its child according to the child's
/// baseline.
/// * [Align], a widget that aligns its child within itself and optionally
/// sizes itself based on the child's size.
/// * [Center], a widget that centers its child within itself.
/// * The [catalog of layout widgets](https://flutter.io/widgets/layout/).
class BaselineBox extends SingleChildRenderObjectWidget {
/// Creates a widget that sets a baseline to its child.
///
/// By default, [baseline] is 0.0 and [fromTop] is false.
/// The [baseline] argument must not be null.
const BaselineBox(
{Key key, this.baseline = 0.0, this.fromTop = false, Widget child})
: assert(baseline != null),
super(key: key, child: child);
/// The number of logical pixels from the bottom or from the top of this
/// widget at which the baseline is positioned.
final double baseline;
/// Whether the baseline distance is measured from the bottom of the widget
/// or from the top
final bool fromTop;
@override
RenderBaselineBox createRenderObject(BuildContext context) =>
new RenderBaselineBox(baseline: baseline, fromTop: fromTop);
@override
void updateRenderObject(BuildContext context, RenderBaselineBox renderObject) {
renderObject
..baseline = baseline
..fromTop = fromTop;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(new DoubleProperty('baseline', baseline));
properties.add(new DiagnosticsProperty<bool>('fromTop', fromTop));
}
}
/// Sets a baseline based on the distance in logical pixels to its
/// bottom or to its top.
///
/// By default, when no values are provided, the baseline coincides with the
/// bottom of the widget, as this is de default behavior for widgets without a
/// baseline. When the param `baseline` has a value, it represents the offset
/// from the bottom.
///
/// If `fromTop` is true, the baseline is the offset from the top of the widget.
///
/// The baseline is set regardless of the [TextBaseline] type, meaning that
/// when the baseline for this widget is queried from the parent, the same
/// baseline will be returned regardless of the [TextBaseline] type queried.
///
class RenderBaselineBox extends RenderProxyBox {
/// Creates a render object that adds a baseline to its child.
///
/// The [baseline] argument must be a finite value.
RenderBaselineBox({
RenderBox child,
@required double baseline,
bool fromTop = false,
}) : assert(baseline != null),
assert(baseline.isFinite),
assert(fromTop != null),
_baseline = baseline,
_fromTop = fromTop,
super(child);
/// Value used as the offset for the baseline.
double get baseline => _baseline;
double _baseline;
set baseline(double value) {
assert(value != null);
assert(value.isFinite);
if (_baseline == value) return;
_baseline = value;
markNeedsLayout();
}
/// Whether the baseline distance is measured from the bottom of the widget
/// or from the top
bool get fromTop => _fromTop;
bool _fromTop;
set fromTop(bool value) {
assert(value != null);
if (_fromTop == value) return;
_fromTop = value;
markNeedsLayout();
}
@override
double computeDistanceToActualBaseline(TextBaseline baselineType) {
return _fromTop ? _baseline : size.height - _baseline;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(new DoubleProperty('baseline', baseline));
properties.add(new DiagnosticsProperty<bool>('fromTop', fromTop));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment