do not show scrollbar thumb for non scrollable views
This commit is contained in:
parent
c840190aec
commit
695f8de2a4
8 changed files with 409 additions and 39 deletions
|
@ -89,12 +89,6 @@ class Constants {
|
|||
licenseUrl: 'https://github.com/benPesso/flutter_decorated_icon/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/benPesso/flutter_decorated_icon',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Draggable Scrollbar',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/flutter-draggable-scrollbar/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/fluttercommunity/flutter-draggable-scrollbar',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Event Bus',
|
||||
license: 'MIT',
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:aves/widgets/collection/grid/section_layout.dart';
|
|||
import 'package:aves/widgets/collection/grid/selector.dart';
|
||||
import 'package:aves/widgets/collection/grid/thumbnail.dart';
|
||||
import 'package:aves/widgets/collection/thumbnail/decorated.dart';
|
||||
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
|
||||
import 'package:aves/widgets/common/basic/insets.dart';
|
||||
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
|
@ -26,7 +27,6 @@ import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
|||
import 'package:aves/widgets/common/providers/highlight_info_provider.dart';
|
||||
import 'package:aves/widgets/common/scaling.dart';
|
||||
import 'package:aves/widgets/common/tile_extent_manager.dart';
|
||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||
|
@ -237,8 +237,8 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
|||
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>(
|
||||
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
|
||||
heightScrollThumb: avesScrollThumbHeight,
|
||||
backgroundColor: Colors.white,
|
||||
scrollThumbHeight: avesScrollThumbHeight,
|
||||
scrollThumbBuilder: avesScrollThumbBuilder(
|
||||
height: avesScrollThumbHeight,
|
||||
backgroundColor: Colors.white,
|
||||
|
|
388
lib/widgets/common/basic/draggable_scrollbar.dart
Normal file
388
lib/widgets/common/basic/draggable_scrollbar.dart
Normal file
|
@ -0,0 +1,388 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/*
|
||||
This is derived from `draggable_scrollbar` package v0.0.4:
|
||||
- removed default thumb builders
|
||||
- allow any `ScrollView` as child
|
||||
- allow any `Widget` as label content
|
||||
- moved out constraints responsibility
|
||||
- various extent & thumb positioning fixes
|
||||
*/
|
||||
|
||||
/// Build the Scroll Thumb and label using the current configuration
|
||||
typedef ScrollThumbBuilder = Widget Function(
|
||||
Color backgroundColor,
|
||||
Animation<double> thumbAnimation,
|
||||
Animation<double> labelAnimation,
|
||||
double height, {
|
||||
Widget labelText,
|
||||
});
|
||||
|
||||
/// Build a Text widget using the current scroll offset
|
||||
typedef LabelTextBuilder = Widget Function(double offsetY);
|
||||
|
||||
/// A widget that will display a BoxScrollView with a ScrollThumb that can be dragged
|
||||
/// for quick navigation of the BoxScrollView.
|
||||
class DraggableScrollbar extends StatefulWidget {
|
||||
/// The background color of the label and thumb
|
||||
final Color backgroundColor;
|
||||
|
||||
/// The height of the scroll thumb
|
||||
final double scrollThumbHeight;
|
||||
|
||||
/// A function that builds a thumb using the current configuration
|
||||
final ScrollThumbBuilder scrollThumbBuilder;
|
||||
|
||||
/// The amount of padding that should surround the thumb
|
||||
final EdgeInsetsGeometry padding;
|
||||
|
||||
/// Determines how quickly the scrollbar will animate in and out
|
||||
final Duration scrollbarAnimationDuration;
|
||||
|
||||
/// How long should the thumb be visible before fading out
|
||||
final Duration scrollbarTimeToFade;
|
||||
|
||||
/// Build a Text widget from the current offset in the BoxScrollView
|
||||
final LabelTextBuilder labelTextBuilder;
|
||||
|
||||
/// The ScrollController for the BoxScrollView
|
||||
final ScrollController controller;
|
||||
|
||||
/// The view that will be scrolled with the scroll thumb
|
||||
final ScrollView child;
|
||||
|
||||
DraggableScrollbar({
|
||||
Key key,
|
||||
@required this.backgroundColor,
|
||||
@required this.scrollThumbHeight,
|
||||
@required this.scrollThumbBuilder,
|
||||
@required this.controller,
|
||||
this.padding,
|
||||
this.scrollbarAnimationDuration = const Duration(milliseconds: 300),
|
||||
this.scrollbarTimeToFade = const Duration(milliseconds: 600),
|
||||
this.labelTextBuilder,
|
||||
@required this.child,
|
||||
}) : assert(controller != null),
|
||||
assert(scrollThumbBuilder != null),
|
||||
assert(child.scrollDirection == Axis.vertical),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
_DraggableScrollbarState createState() => _DraggableScrollbarState();
|
||||
|
||||
static Widget buildScrollThumbAndLabel({
|
||||
@required Widget scrollThumb,
|
||||
@required Color backgroundColor,
|
||||
@required Animation<double> thumbAnimation,
|
||||
@required Animation<double> labelAnimation,
|
||||
@required Widget labelText,
|
||||
}) {
|
||||
final scrollThumbAndLabel = labelText == null
|
||||
? scrollThumb
|
||||
: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ScrollLabel(
|
||||
animation: labelAnimation,
|
||||
child: labelText,
|
||||
backgroundColor: backgroundColor,
|
||||
),
|
||||
scrollThumb,
|
||||
],
|
||||
);
|
||||
return SlideFadeTransition(
|
||||
animation: thumbAnimation,
|
||||
child: scrollThumbAndLabel,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ScrollLabel extends StatelessWidget {
|
||||
final Animation<double> animation;
|
||||
final Color backgroundColor;
|
||||
final Widget child;
|
||||
|
||||
const ScrollLabel({
|
||||
Key key,
|
||||
@required this.child,
|
||||
@required this.animation,
|
||||
@required this.backgroundColor,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(right: 12.0),
|
||||
child: Material(
|
||||
elevation: 4.0,
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16.0)),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DraggableScrollbarState extends State<DraggableScrollbar> with TickerProviderStateMixin {
|
||||
final ValueNotifier<double> _thumbOffsetNotifier = ValueNotifier(0), _viewOffsetNotifier = ValueNotifier(0);
|
||||
bool _isDragInProcess = false;
|
||||
|
||||
AnimationController _thumbAnimationController;
|
||||
Animation<double> _thumbAnimation;
|
||||
AnimationController _labelAnimationController;
|
||||
Animation<double> _labelAnimation;
|
||||
Timer _fadeoutTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_thumbAnimationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: widget.scrollbarAnimationDuration,
|
||||
);
|
||||
|
||||
_thumbAnimation = CurvedAnimation(
|
||||
parent: _thumbAnimationController,
|
||||
curve: Curves.fastOutSlowIn,
|
||||
);
|
||||
|
||||
_labelAnimationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: widget.scrollbarAnimationDuration,
|
||||
);
|
||||
|
||||
_labelAnimation = CurvedAnimation(
|
||||
parent: _labelAnimationController,
|
||||
curve: Curves.fastOutSlowIn,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_thumbAnimationController.dispose();
|
||||
_labelAnimationController.dispose();
|
||||
_fadeoutTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
ScrollController get controller => widget.controller;
|
||||
|
||||
double get thumbMaxScrollExtent => context.size.height - widget.scrollThumbHeight - (widget.padding?.vertical ?? 0.0);
|
||||
|
||||
double get thumbMinScrollExtent => 0.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NotificationListener<ScrollNotification>(
|
||||
onNotification: (notification) {
|
||||
_onScrollNotification(notification);
|
||||
return false;
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
RepaintBoundary(
|
||||
child: widget.child,
|
||||
),
|
||||
RepaintBoundary(
|
||||
child: GestureDetector(
|
||||
onVerticalDragStart: _onVerticalDragStart,
|
||||
onVerticalDragUpdate: _onVerticalDragUpdate,
|
||||
onVerticalDragEnd: _onVerticalDragEnd,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _thumbOffsetNotifier,
|
||||
builder: (context, thumbOffset, child) => Container(
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
padding: EdgeInsets.only(top: thumbOffset) + widget.padding,
|
||||
child: widget.scrollThumbBuilder(
|
||||
widget.backgroundColor,
|
||||
_thumbAnimation,
|
||||
_labelAnimation,
|
||||
widget.scrollThumbHeight,
|
||||
labelText: (widget.labelTextBuilder != null && _isDragInProcess)
|
||||
? ValueListenableBuilder(
|
||||
valueListenable: _viewOffsetNotifier,
|
||||
builder: (context, viewOffset, child) => widget.labelTextBuilder(viewOffset + thumbOffset),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onScrollNotification(ScrollNotification notification) {
|
||||
final scrollMetrics = notification.metrics;
|
||||
|
||||
// do not update the thumb if we cannot actually scroll
|
||||
if (scrollMetrics.minScrollExtent >= scrollMetrics.maxScrollExtent) return;
|
||||
|
||||
_viewOffsetNotifier.value = scrollMetrics.pixels;
|
||||
|
||||
// we update the thumb position from the scrolled offset
|
||||
// when the user is not dragging the thumb
|
||||
if (!_isDragInProcess) {
|
||||
if (notification is ScrollUpdateNotification) {
|
||||
_thumbOffsetNotifier.value = (scrollMetrics.pixels / scrollMetrics.maxScrollExtent * thumbMaxScrollExtent).clamp(thumbMinScrollExtent, thumbMaxScrollExtent);
|
||||
}
|
||||
|
||||
if (notification is ScrollUpdateNotification || notification is OverscrollNotification) {
|
||||
_showThumb();
|
||||
_scheduleFadeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _onVerticalDragStart(DragStartDetails details) {
|
||||
_labelAnimationController.forward();
|
||||
_fadeoutTimer?.cancel();
|
||||
setState(() => _isDragInProcess = true);
|
||||
}
|
||||
|
||||
void _onVerticalDragUpdate(DragUpdateDetails details) {
|
||||
_showThumb();
|
||||
if (_isDragInProcess) {
|
||||
// thumb offset
|
||||
_thumbOffsetNotifier.value = (_thumbOffsetNotifier.value + details.delta.dy).clamp(thumbMinScrollExtent, thumbMaxScrollExtent);
|
||||
|
||||
// scroll offset
|
||||
final min = controller.position.minScrollExtent;
|
||||
final max = controller.position.maxScrollExtent;
|
||||
controller.jumpTo((_thumbOffsetNotifier.value / thumbMaxScrollExtent * max).clamp(min, max));
|
||||
}
|
||||
}
|
||||
|
||||
void _onVerticalDragEnd(DragEndDetails details) {
|
||||
_scheduleFadeout();
|
||||
setState(() => _isDragInProcess = false);
|
||||
}
|
||||
|
||||
void _showThumb() {
|
||||
if (_thumbAnimationController.status != AnimationStatus.forward) {
|
||||
_thumbAnimationController.forward();
|
||||
}
|
||||
}
|
||||
|
||||
void _scheduleFadeout() {
|
||||
_fadeoutTimer?.cancel();
|
||||
_fadeoutTimer = Timer(widget.scrollbarTimeToFade, () {
|
||||
_thumbAnimationController.reverse();
|
||||
_labelAnimationController.reverse();
|
||||
_fadeoutTimer = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws 2 triangles like arrow up and arrow down
|
||||
class ArrowCustomPainter extends CustomPainter {
|
||||
Color color;
|
||||
|
||||
ArrowCustomPainter(this.color);
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()..color = color;
|
||||
const width = 12.0;
|
||||
const height = 8.0;
|
||||
final baseX = size.width / 2;
|
||||
final baseY = size.height / 2;
|
||||
|
||||
canvas.drawPath(
|
||||
_trianglePath(Offset(baseX, baseY - 2.0), width, height, true),
|
||||
paint,
|
||||
);
|
||||
canvas.drawPath(
|
||||
_trianglePath(Offset(baseX, baseY + 2.0), width, height, false),
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
static Path _trianglePath(Offset o, double width, double height, bool isUp) {
|
||||
return Path()
|
||||
..moveTo(o.dx, o.dy)
|
||||
..lineTo(o.dx + width, o.dy)
|
||||
..lineTo(o.dx + (width / 2), isUp ? o.dy - height : o.dy + height)
|
||||
..close();
|
||||
}
|
||||
}
|
||||
|
||||
///This cut 2 lines in arrow shape
|
||||
class ArrowClipper extends CustomClipper<Path> {
|
||||
@override
|
||||
Path getClip(Size size) {
|
||||
final path = Path();
|
||||
path.lineTo(0.0, size.height);
|
||||
path.lineTo(size.width, size.height);
|
||||
path.lineTo(size.width, 0.0);
|
||||
path.lineTo(0.0, 0.0);
|
||||
path.close();
|
||||
|
||||
const arrowWidth = 8.0;
|
||||
final startPointX = (size.width - arrowWidth) / 2;
|
||||
var startPointY = size.height / 2 - arrowWidth / 2;
|
||||
path.moveTo(startPointX, startPointY);
|
||||
path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2);
|
||||
path.lineTo(startPointX + arrowWidth, startPointY);
|
||||
path.lineTo(startPointX + arrowWidth, startPointY + 1.0);
|
||||
path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2 + 1.0);
|
||||
path.lineTo(startPointX, startPointY + 1.0);
|
||||
path.close();
|
||||
|
||||
startPointY = size.height / 2 + arrowWidth / 2;
|
||||
path.moveTo(startPointX + arrowWidth, startPointY);
|
||||
path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2);
|
||||
path.lineTo(startPointX, startPointY);
|
||||
path.lineTo(startPointX, startPointY - 1.0);
|
||||
path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2 - 1.0);
|
||||
path.lineTo(startPointX + arrowWidth, startPointY - 1.0);
|
||||
path.close();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
|
||||
}
|
||||
|
||||
class SlideFadeTransition extends StatelessWidget {
|
||||
final Animation<double> animation;
|
||||
final Widget child;
|
||||
|
||||
const SlideFadeTransition({
|
||||
Key key,
|
||||
@required this.animation,
|
||||
@required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: animation,
|
||||
builder: (context, child) => animation.value == 0.0 ? Container() : child,
|
||||
child: SlideTransition(
|
||||
position: Tween(
|
||||
begin: Offset(0.3, 0.0),
|
||||
end: Offset(0.0, 0.0),
|
||||
).animate(animation),
|
||||
child: FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const double avesScrollThumbHeight = 48;
|
||||
|
@ -35,7 +35,6 @@ ScrollThumbBuilder avesScrollThumbBuilder({
|
|||
thumbAnimation: thumbAnimation,
|
||||
labelAnimation: labelAnimation,
|
||||
labelText: labelText,
|
||||
alwaysVisibleScrollThumb: false,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,16 +6,18 @@ import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
|||
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// `Magnifier` is derived from `photo_view` package v0.9.2:
|
||||
/// - removed image related aspects to focus on a general purpose pan/scale viewer (à la `InteractiveViewer`)
|
||||
/// - removed rotation and many customization parameters
|
||||
/// - removed ignorable/ignoring partial notifiers
|
||||
/// - formatted, renamed and reorganized
|
||||
/// - fixed gesture recognizers when used inside a scrollable widget like `PageView`
|
||||
/// - fixed corner hit detection when in containers scrollable in both axes
|
||||
/// - fixed corner hit detection issues due to imprecise double comparisons
|
||||
/// - added single & double tap position feedback
|
||||
/// - fixed focus when scaling by double-tap/pinch
|
||||
/*
|
||||
`Magnifier` is derived from `photo_view` package v0.9.2:
|
||||
- removed image related aspects to focus on a general purpose pan/scale viewer (à la `InteractiveViewer`)
|
||||
- removed rotation and many customization parameters
|
||||
- removed ignorable/ignoring partial notifiers
|
||||
- formatted, renamed and reorganized
|
||||
- fixed gesture recognizers when used inside a scrollable widget like `PageView`
|
||||
- fixed corner hit detection when in containers scrollable in both axes
|
||||
- fixed corner hit detection issues due to imprecise double comparisons
|
||||
- added single & double tap position feedback
|
||||
- fixed focus when scaling by double-tap/pinch
|
||||
*/
|
||||
class Magnifier extends StatefulWidget {
|
||||
const Magnifier({
|
||||
Key key,
|
||||
|
@ -33,16 +35,16 @@ class Magnifier extends StatefulWidget {
|
|||
|
||||
final Widget child;
|
||||
|
||||
/// The size of the custom [child]. This value is used to compute the relation between the child and the container's size to calculate the scale value.
|
||||
// The size of the custom [child]. This value is used to compute the relation between the child and the container's size to calculate the scale value.
|
||||
final Size childSize;
|
||||
|
||||
/// Defines the maximum size in which the image will be allowed to assume, it is proportional to the original image size.
|
||||
// Defines the maximum size in which the image will be allowed to assume, it is proportional to the original image size.
|
||||
final ScaleLevel maxScale;
|
||||
|
||||
/// Defines the minimum size in which the image will be allowed to assume, it is proportional to the original image size.
|
||||
// Defines the minimum size in which the image will be allowed to assume, it is proportional to the original image size.
|
||||
final ScaleLevel minScale;
|
||||
|
||||
/// Defines the size the image will assume when the component is initialized, it is proportional to the original image size.
|
||||
// Defines the size the image will assume when the component is initialized, it is proportional to the original image size.
|
||||
final ScaleLevel initialScale;
|
||||
|
||||
final MagnifierController controller;
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:aves/model/filters/filters.dart';
|
|||
import 'package:aves/model/highlight.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/collection_source.dart';
|
||||
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
|
||||
import 'package:aves/widgets/common/basic/insets.dart';
|
||||
import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
|
@ -20,7 +21,6 @@ import 'package:aves/widgets/drawer/app_drawer.dart';
|
|||
import 'package:aves/widgets/filter_grids/common/decorated_filter_chip.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/section_keys.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/section_layout.dart';
|
||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||
|
@ -192,8 +192,8 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
return Selector<MediaQueryData, double>(
|
||||
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
|
||||
heightScrollThumb: avesScrollThumbHeight,
|
||||
backgroundColor: Colors.white,
|
||||
scrollThumbHeight: avesScrollThumbHeight,
|
||||
scrollThumbBuilder: avesScrollThumbBuilder(
|
||||
height: avesScrollThumbHeight,
|
||||
backgroundColor: Colors.white,
|
||||
|
|
|
@ -148,15 +148,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
draggable_scrollbar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "3b823ae0a9def4edec62771f18e6348312bfce15"
|
||||
url: "git://github.com/deckerst/flutter-draggable-scrollbar.git"
|
||||
source: git
|
||||
version: "0.0.4"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -34,10 +34,6 @@ dependencies:
|
|||
charts_flutter:
|
||||
collection:
|
||||
decorated_icon:
|
||||
draggable_scrollbar:
|
||||
# path: ../flutter-draggable-scrollbar
|
||||
git:
|
||||
url: git://github.com/deckerst/flutter-draggable-scrollbar.git
|
||||
event_bus:
|
||||
expansion_tile_card:
|
||||
# path: ../expansion_tile_card
|
||||
|
|
Loading…
Reference in a new issue