Show arrow indicator on toolbar (#245)

pull/249/head
Till Friebe 4 years ago committed by GitHub
parent aba8032b8d
commit 16d6f243b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      lib/src/widgets/toolbar.dart
  2. 125
      lib/src/widgets/toolbar/arrow_indicated_button_list.dart

@ -6,6 +6,7 @@ import 'package:image_picker/image_picker.dart';
import '../models/documents/attribute.dart';
import 'controller.dart';
import 'toolbar/arrow_indicated_button_list.dart';
import 'toolbar/clear_format_button.dart';
import 'toolbar/color_button.dart';
import 'toolbar/history_button.dart';
@ -316,21 +317,9 @@ class _QuillToolbarState extends State<QuillToolbar> {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
constraints: BoxConstraints.tightFor(height: widget.preferredSize.height),
color: Theme.of(context).canvasColor,
child: CustomScrollView(
scrollDirection: Axis.horizontal,
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: widget.children,
),
),
],
),
child: ArrowIndicatedButtonList(buttons: widget.children),
);
}
}

@ -0,0 +1,125 @@
import 'dart:async';
import 'package:flutter/material.dart';
/// Scrollable list with arrow indicators.
///
/// The arrow indicators are automatically hidden if the list is not
/// scrollable in the direction of the respective arrow.
class ArrowIndicatedButtonList extends StatefulWidget {
const ArrowIndicatedButtonList({required this.buttons, Key? key})
: super(key: key);
final List<Widget> buttons;
@override
_ArrowIndicatedButtonListState createState() =>
_ArrowIndicatedButtonListState();
}
class _ArrowIndicatedButtonListState extends State<ArrowIndicatedButtonList>
with WidgetsBindingObserver {
final ScrollController _controller = ScrollController();
bool _showLeftArrow = false;
bool _showRightArrow = false;
@override
void initState() {
super.initState();
_controller.addListener(_handleScroll);
// Listening to the WidgetsBinding instance is necessary so that we can
// hide the arrows when the window gets a new size and thus the toolbar
// becomes scrollable/unscrollable.
WidgetsBinding.instance!.addObserver(this);
// Workaround to allow the scroll controller attach to our ListView so that
// we can detect if overflow arrows need to be shown on init.
Timer.run(_handleScroll);
}
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
_buildLeftArrow(),
_buildScrollableList(),
_buildRightColor(),
],
);
}
@override
void didChangeMetrics() => _handleScroll();
@override
void dispose() {
_controller.dispose();
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
void _handleScroll() {
setState(() {
_showLeftArrow =
_controller.position.minScrollExtent != _controller.position.pixels;
_showRightArrow =
_controller.position.maxScrollExtent != _controller.position.pixels;
});
}
Widget _buildLeftArrow() {
return SizedBox(
width: 8,
child: Transform.translate(
// Move the icon a few pixels to center it
offset: const Offset(-5, 0),
child: _showLeftArrow ? const Icon(Icons.arrow_left, size: 18) : null,
),
);
}
Widget _buildScrollableList() {
return Expanded(
child: ScrollConfiguration(
// Remove the glowing effect, as we already have the arrow indicators
behavior: _NoGlowBehavior(),
// The CustomScrollView is necessary so that the children are not
// stretched to the height of the toolbar, https://bit.ly/3uC3bjI
child: CustomScrollView(
scrollDirection: Axis.horizontal,
controller: _controller,
physics: const ClampingScrollPhysics(),
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: widget.buttons,
),
)
],
),
),
);
}
Widget _buildRightColor() {
return SizedBox(
width: 8,
child: Transform.translate(
// Move the icon a few pixels to center it
offset: const Offset(-5, 0),
child: _showRightArrow ? const Icon(Icons.arrow_right, size: 18) : null,
),
);
}
}
/// ScrollBehavior without the Material glow effect.
class _NoGlowBehavior extends ScrollBehavior {
@override
Widget buildViewportChrome(BuildContext _, Widget child, AxisDirection __) {
return child;
}
}
Loading…
Cancel
Save