Skip to content
Open
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
108 changes: 79 additions & 29 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,105 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Resizable Widget Example',
theme: ThemeData.dark(),
home: const MyPage(),
);
}
}

class MyPage extends StatelessWidget {
class MyPage extends StatefulWidget {
const MyPage({Key? key}) : super(key: key);

@override
State<MyPage> createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
var textDirection = TextDirection.rtl;

@override
Widget build(BuildContext context) {
final rtl = textDirection == TextDirection.rtl;
return Scaffold(
appBar: AppBar(
title: const Text('Resizable Widget Example'),
),
body: ResizableWidget(
isHorizontalSeparator: false,
isDisabledSmartHide: false,
separatorColor: Colors.white12,
separatorSize: 4,
onResized: _printResizeInfo,
children: [
Container(color: Colors.greenAccent),
ResizableWidget(
isHorizontalSeparator: true,
separatorColor: Colors.blue,
separatorSize: 10,
children: [
Container(color: Colors.greenAccent),
ResizableWidget(
children: [
Container(color: Colors.greenAccent),
Container(color: Colors.yellowAccent),
Container(color: Colors.redAccent),
],
percentages: const [0.2, 0.5, 0.3],
),
Container(color: Colors.redAccent),
],
title: Text('Resizable Widget Example (${rtl ? 'Right-to-Left' : 'Left-to-Right'})'),
actions: [
IconButton(
icon: Icon(rtl ? Icons.subdirectory_arrow_left : Icons.subdirectory_arrow_right),
onPressed: () {
setState(() => textDirection = rtl ? TextDirection.ltr : TextDirection.rtl);
},
),
Container(color: Colors.redAccent),
],
),
body: Directionality(
textDirection: textDirection,
child: ResizableWidget(
isHorizontalSeparator: false,
isDisabledSmartHide: false,
separatorColor: Colors.white12,
separatorSize: 4,
onResized: _printResizeInfo,
constraints: const [
BoxConstraints(minWidth: 100),
null,
null,
],
children: [
Container(
color: Colors.green,
child: const Center(
child: Text('Min Width is 100', style: TextStyle(color: Colors.black)),
),
),
ResizableWidget(
isHorizontalSeparator: true,
separatorColor: Colors.blue,
separatorSize: 10,
constraints: const [
BoxConstraints(minHeight: 200),
BoxConstraints(minHeight: 100, maxHeight: 250),
null,
],
children: [
Container(
color: Colors.amber,
child: const Center(
child: Text('Min Height is 200', style: TextStyle(color: Colors.black)),
),
),
ResizableWidget(
constraints: const [
null,
BoxConstraints(minHeight: 150, maxHeight: 200),
null,
],
children: [
Container(color: Colors.greenAccent),
Container(
color: Colors.yellowAccent,
child: const Center(
child: Text('Min Height is 100\nMax Height is 250', style: TextStyle(color: Colors.black)),
),
),
Container(color: Colors.redAccent),
],
percentages: const [0.2, 0.5, 0.3],
),
Container(color: Colors.redAccent),
],
),
Container(color: Colors.redAccent),
],
),
),
);
}

void _printResizeInfo(List<WidgetSizeInfo> dataList) {
// ignore: avoid_print
print(dataList.map((x) => '(${x.size}, ${x.percentage}%)').join(", "));
// print(dataList.map((x) => '(${x.size}, ${x.percentage}%)').join(", "));
}
}
51 changes: 33 additions & 18 deletions lib/src/resizable_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ class ResizableWidget extends StatefulWidget {
/// If this value is [null], [children] will be split into the same size.
final List<double>? percentages;

/// Constraints among the [ResizableWidget] children.
///
/// Used to force the widget to doesn't break constraints sizes.
///
/// Sets the default [children] constraints sizes.
///
/// If you set this value,
/// the length of [constraints] must match the one of [children].
/// If you don't want to set constraints to one child, just set it to [null] or [BoxConstraints()].
///
/// If this value is [null], [children] will be resized without any constraints.
final List<BoxConstraints?>? constraints;

/// When set to true, creates horizontal separators.
@Deprecated('Use [isHorizontalSeparator] instead')
final bool isColumnChildren;
Expand Down Expand Up @@ -53,8 +66,8 @@ class ResizableWidget extends StatefulWidget {
Key? key,
required this.children,
this.percentages,
@Deprecated('Use [isHorizontalSeparator] instead')
this.isColumnChildren = false,
this.constraints,
@Deprecated('Use [isHorizontalSeparator] instead') this.isColumnChildren = false,
this.isHorizontalSeparator = false,
this.isDisabledSmartHide = false,
this.separatorSize = 4,
Expand All @@ -63,8 +76,8 @@ class ResizableWidget extends StatefulWidget {
}) : super(key: key) {
assert(children.isNotEmpty);
assert(percentages == null || percentages!.length == children.length);
assert(percentages == null ||
percentages!.reduce((value, element) => value + element) == 1);
assert(constraints == null || constraints!.length == children.length);
assert(percentages == null || percentages!.reduce((value, element) => value + element) == 1);
}

@override
Expand All @@ -85,27 +98,29 @@ class _ResizableWidgetState extends State<ResizableWidget> {

@override
Widget build(BuildContext context) => LayoutBuilder(
builder: (context, constraints) {
_controller.setSizeIfNeeded(constraints);
return StreamBuilder(
stream: _controller.eventStream.stream,
builder: (context, snapshot) => _info.isHorizontalSeparator
? Column(
children: _controller.children.map(_buildChild).toList())
: Row(children: _controller.children.map(_buildChild).toList()),
);
},
builder: (context, constraints) {
_controller.setSizeIfNeeded(constraints);
return StreamBuilder(
stream: _controller.eventStream.stream,
builder: (context, snapshot) => _info.isHorizontalSeparator
? Column(children: _controller.children.map(_buildChild).toList())
: Row(children: _controller.children.map(_buildChild).toList()),
);
},
);

Widget _buildChild(ResizableWidgetChildData child) {
if (child.widget is Separator) {
return child.widget;
}

return SizedBox(
width: _info.isHorizontalSeparator ? double.infinity : child.size,
height: _info.isHorizontalSeparator ? child.size : double.infinity,
child: child.widget,
return ConstrainedBox(
constraints: child.constraints ?? const BoxConstraints(),
child: SizedBox(
width: _info.isHorizontalSeparator ? double.infinity : child.size,
height: _info.isHorizontalSeparator ? child.size : double.infinity,
child: child.widget,
),
);
}
}
2 changes: 2 additions & 0 deletions lib/src/resizable_widget_args_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'resizable_widget.dart';
class ResizableWidgetArgsInfo {
final List<Widget> children;
final List<double>? percentages;
final List<BoxConstraints?>? constraints;
final bool isHorizontalSeparator;
final bool isDisabledSmartHide;
final double separatorSize;
Expand All @@ -13,6 +14,7 @@ class ResizableWidgetArgsInfo {
ResizableWidgetArgsInfo(ResizableWidget widget)
: children = widget.children,
percentages = widget.percentages,
constraints = widget.constraints,
isHorizontalSeparator =
// TODO: delete the deprecated member on the next minor update.
// ignore: deprecated_member_use_from_same_package
Expand Down
3 changes: 2 additions & 1 deletion lib/src/resizable_widget_child_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ class ResizableWidgetChildData {
final Widget widget;
double? size;
double? percentage;
BoxConstraints? constraints;
double? defaultPercentage;
double? hidingPercentage;
ResizableWidgetChildData(this.widget, this.percentage);
ResizableWidgetChildData(this.widget, this.percentage, this.constraints);
}
8 changes: 4 additions & 4 deletions lib/src/resizable_widget_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ class ResizableWidgetController {
_model.callOnResized();
}

void resize(int separatorIndex, Offset offset) {
_model.resize(separatorIndex, offset);
void resize(BuildContext context, int separatorIndex, Offset offset) {
_model.resize(context, separatorIndex, offset);

eventStream.add(this);
_model.callOnResized();
}

void tryHideOrShow(int separatorIndex) {
final result = _model.tryHideOrShow(separatorIndex);
void tryHideOrShow(BuildContext context, int separatorIndex) {
final result = _model.tryHideOrShow(context, separatorIndex);

if (result) {
eventStream.add(this);
Expand Down
Loading