From 82a0ddb618e1514936488cb16c4f88453f2e562c Mon Sep 17 00:00:00 2001 From: Toshiaki Hayashi Date: Fri, 4 Jun 2021 22:40:06 +0900 Subject: [PATCH] * Added indicator / activeIndicator fields. These fields can set grip indicator for inform the user that splitter bar is draggable. * Added SplitIndicator class. This class is a sample implementation of indicator. --- CHANGELOG.md | 5 +++ README.md | 10 +++++ example/lib/main.dart | 10 +++++ example/pubspec.lock | 8 ++-- lib/split_view.dart | 100 +++++++++++++++++++++++++++++++++++++++++- pubspec.lock | 6 +-- pubspec.yaml | 2 +- 7 files changed, 131 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bdd3d8..20ddb50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.1.0 + +* Added indicator / activeIndicator fields. These fields can set grip indicator for inform the user that splitter bar is draggable. +* Added SplitIndicator class. This class is a sample implementation of indicator. + ## 3.0.0 * This version contains breaking changes. diff --git a/README.md b/README.md index 34d11ed..afc9ca2 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,11 @@ class _MyHomePageState extends State { children: [ SplitView( viewMode: SplitViewMode.Horizontal, + indicator: SplitIndicator(viewMode: SplitViewMode.Horizontal), + activeIndicator: SplitIndicator( + viewMode: SplitViewMode.Horizontal, + isActive: true, + ), children: [ Container( child: Center(child: Text("View1")), @@ -72,6 +77,11 @@ class _MyHomePageState extends State { ), ], viewMode: SplitViewMode.Vertical, + indicator: SplitIndicator(viewMode: SplitViewMode.Vertical), + activeIndicator: SplitIndicator( + viewMode: SplitViewMode.Vertical, + isActive: true, + ), controller: SplitViewController(limits: [null, WeightLimit(max: 0.5)]), onWeightChanged: (w) => print("Vertical $w"), ), diff --git a/example/lib/main.dart b/example/lib/main.dart index 5c3a728..fa29990 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -37,6 +37,11 @@ class _MyHomePageState extends State { children: [ SplitView( viewMode: SplitViewMode.Horizontal, + indicator: SplitIndicator(viewMode: SplitViewMode.Horizontal), + activeIndicator: SplitIndicator( + viewMode: SplitViewMode.Horizontal, + isActive: true, + ), children: [ Container( child: Center(child: Text("View1")), @@ -63,6 +68,11 @@ class _MyHomePageState extends State { ), ], viewMode: SplitViewMode.Vertical, + indicator: SplitIndicator(viewMode: SplitViewMode.Vertical), + activeIndicator: SplitIndicator( + viewMode: SplitViewMode.Vertical, + isActive: true, + ), controller: SplitViewController(limits: [null, WeightLimit(max: 0.5)]), onWeightChanged: (w) => print("Vertical $w"), ), diff --git a/example/pubspec.lock b/example/pubspec.lock index 9dbea97..9a4c8a5 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" boolean_selector: dependency: transitive description: @@ -99,14 +99,14 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" split_view: dependency: "direct main" description: path: ".." relative: true source: path - version: "2.1.1+1" + version: "3.1.0" stack_trace: dependency: transitive description: @@ -141,7 +141,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" typed_data: dependency: transitive description: diff --git a/lib/split_view.dart b/lib/split_view.dart index 264c9c4..d86f723 100644 --- a/lib/split_view.dart +++ b/lib/split_view.dart @@ -35,6 +35,12 @@ class SplitView extends StatefulWidget { /// Called when the user moves the grip. final ValueChanged>? onWeightChanged; + /// Grip indicator. + final Widget? indicator; + + /// Grip indicator for active state. + final Widget? activeIndicator; + /// Creates a [SplitView]. SplitView({ Key? key, @@ -45,6 +51,8 @@ class SplitView extends StatefulWidget { this.gripColor = defaultGripColor, this.gripColorActive = defaultGripColorActive, this.onWeightChanged, + this.indicator, + this.activeIndicator, }) : super(key: key); @override @@ -154,7 +162,14 @@ class _SplitViewState extends State { _changeWeights(diff, viewsHeight, i); }, child: Container( - color: _activeIndex == i ? _gripColor : widget.gripColor), + color: _activeIndex == i ? _gripColor : widget.gripColor, + alignment: Alignment.center, + child: _activeIndex == i + ? widget.activeIndicator != null + ? widget.activeIndicator + : widget.indicator + : widget.indicator, + ), ), ), )); @@ -228,7 +243,14 @@ class _SplitViewState extends State { _changeWeights(diff, viewsWidth, i); }, child: Container( - color: _activeIndex == i ? _gripColor : widget.gripColor), + color: _activeIndex == i ? _gripColor : widget.gripColor, + alignment: Alignment.center, + child: _activeIndex == i + ? widget.activeIndicator != null + ? widget.activeIndicator + : widget.indicator + : widget.indicator, + ), ), ), )); @@ -345,6 +367,80 @@ class WeightLimit { WeightLimit({this.min, this.max}); } +/// A SplitIndicator class. +class SplitIndicator extends StatelessWidget { + /// The [viewMode] specifies how to arrange views. + final SplitViewMode viewMode; + + /// Specifies true when it is used in the active state. + final bool isActive; + + /// Specified indicator color. + final Color color; + + const SplitIndicator({ + required this.viewMode, + this.isActive = false, + this.color = Colors.white, + }); + + @override + Widget build(BuildContext context) { + return SizedBox.expand( + child: CustomPaint( + painter: _SplitIndicatorPainter( + viewMode: this.viewMode, + isActive: this.isActive, + color: this.color, + ), + ), + ); + } +} + +class _SplitIndicatorPainter extends CustomPainter { + final SplitViewMode viewMode; + final bool isActive; + final Color color; + + static const double DEFAULT_STROKE_WIDTH_RATIO = 0.2; + static const double ACTIVE_STROKE_WIDTH_RATIO = 0.4; + static const double STROKE_LENGTH = 0.15; + + _SplitIndicatorPainter({ + required this.viewMode, + required this.isActive, + required this.color, + }); + + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint()..color = this.color; + double x1, x2, y1, y2; + double strokeWidthRatio = + this.isActive ? ACTIVE_STROKE_WIDTH_RATIO : DEFAULT_STROKE_WIDTH_RATIO; + if (this.viewMode == SplitViewMode.Horizontal) { + x1 = x2 = size.width / 2; + y1 = size.height * (1 - STROKE_LENGTH) / 2; + y2 = y1 + size.height * STROKE_LENGTH; + paint.strokeWidth = size.width * strokeWidthRatio; + paint.strokeCap = StrokeCap.round; + } else { + x1 = size.width * (1 - STROKE_LENGTH) / 2; + x2 = x1 + size.width * STROKE_LENGTH; + y1 = y2 = size.height / 2; + paint.strokeWidth = size.height * strokeWidthRatio; + paint.strokeCap = StrokeCap.round; + } + canvas.drawLine(Offset(x1, y1), Offset(x2, y2), paint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return true; + } +} + /// Arranges view order. enum SplitViewMode { /// Arranges vertically. diff --git a/pubspec.lock b/pubspec.lock index 49a0ce6..ad6d1df 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" boolean_selector: dependency: transitive description: @@ -92,7 +92,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -127,7 +127,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c07df29..4e5b7b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: split_view description: This wedget provides horizontal or vertical split view for flutter. -version: 3.0.0 +version: 3.1.0 homepage: https://github.com/toshiaki-h/split_view environment: