cairacshields / flutter_web_scrollbar_plugin Goto Github PK
View Code? Open in Web Editor NEWhttps://pub.dev/packages/flutter_web_scrollbar
License: MIT License
https://pub.dev/packages/flutter_web_scrollbar
License: MIT License
How to make sure the web scrollbar and the scrolling of the page are synced? Right now if I scroll up and down with the mouse wheel, the scrolling works, but the web scrollbar doesn't follow along with the page movement.
I've closed my 2 issues because they were solved with this implementation:
This code contains:
tap on the handle to go to that place, and handle scrolling with the page.
For this to work, there is a little change in the _landingPageState from your pub.dev example.
Its in the end of this new code.
library flutter_web_scrollbar;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:flutter/scheduler.dart';
/// Welcome to the FlutterWebScrollBar Plugin!
/// In order to assist with using the plugin directly,
/// I've set up this introduction.
///
/// Before you begin implementing this scrollbar for
/// your web project, it's important to note that the plugin is
/// still under development.
///
/// We are actively working on things like mouse scroll detection, and
/// automatically determining the height of your page content.
///
/// Please feel free to file an issue report at the repository found here:
/// https://github.com/cairacshields/flutter_web_scrollbar_plugin
class FlutterWebScrollBar {
static void registerWith(Registrar registrar) {
final MethodChannel channel = MethodChannel(
'plugins.flutter.io/flutter_web_scrollbar',
const StandardMethodCodec(),
registrar.messenger);
final FlutterWebScrollBar instance = FlutterWebScrollBar();
channel.setMethodCallHandler(instance.handleMethodCall);
}
Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'flutter_web_scrollbar':
ScrollController controller = call.arguments['controller'];
Function scrollCallBack = call.arguments['scrollCallBack'];
double proportion = call.arguments['proportion'];
Color backgroundColor = call.arguments['scrollBarBackgroundColor'];
double barWidth = call.arguments['scrollBarWidth'];
Color handleColor = call.arguments['dragHandleColor'];
double handleWidth = call.arguments['dragHandleWidth'];
double handleHeight = call.arguments['dragHandleHeight'];
double handleBorderRadius = call.arguments['dragHandleBorderRadius'];
return FlutterWebScroller(
controller,
scrollCallBack,
proportion,
scrollBarBackgroundColor: backgroundColor,
scrollBarWidth: barWidth,
dragHandleColor: handleColor,
dragHandleWidth: handleWidth,
dragHandleHeight: handleHeight,
dragHandleBorderRadius: handleBorderRadius,
);
default:
throw PlatformException(
code: 'Unimplemented',
details:
"The flutter_web_scrollbar plugin for web doesn't implement "
"the method '${call.method}'");
}
}
}
class FlutterWebScroller extends StatefulWidget {
final ScrollController controller;
/// Required! CallBack function used to update the scrollable content with the new drag position
final Function scrollCallBack;
final double proportion;
/// Optional: Background color of the scrollbar
final Color scrollBarBackgroundColor;
///Optional: Width of the scrollbar
final double scrollBarWidth;
///Optional: Color of the drag handle
final Color dragHandleColor;
///Optional: Width of the drag handle
final double dragHandleWidth;
///Optional: Height of the drag handle
final double dragHandleHeight;
///Optional: Border Radius of the drag handle
final double dragHandleBorderRadius;
FlutterWebScroller(this.controller, this.scrollCallBack, this.proportion,
{this.scrollBarBackgroundColor = Colors.black12,
this.dragHandleColor = Colors.grey,
this.scrollBarWidth = 20.0,
this.dragHandleHeight = 40.0,
this.dragHandleWidth = 15.0,
this.dragHandleBorderRadius = 3.0});
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _FlutterWebScrollerState();
}
}
//static double _max = 0;
class _FlutterWebScrollerState extends State<FlutterWebScroller> {
static double _offset = 0;
_scrollListener() {
setState(() {
_offset = widget.controller.position.pixels / widget.proportion;
});
}
@override
void initState() {
widget.controller.addListener(_scrollListener);
SchedulerBinding.instance.addPostFrameCallback((_) {
_updateScroll(0); // this is a workaround for the _max initial value of 0
});
super.initState();
}
_updateScroll(double towhere) {
widget.scrollCallBack(towhere);
setState(() {
if (towhere >= 0) {
/// Update the offset of the drag handle to push it down or shift it up
_offset = towhere;
double maxHeight =
MediaQuery.of(context).size.height - widget.dragHandleHeight;
_offset = (_offset > maxHeight) ? maxHeight : _offset;
}
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (TapDownDetails details) =>
_updateScroll(details.globalPosition.dy),
child: Container(
alignment: Alignment.centerRight,
height: MediaQuery.of(context).size.height,
width: widget.scrollBarWidth,
margin: EdgeInsets.only(
left:
MediaQuery.of(context).size.width - widget.scrollBarWidth),
decoration: BoxDecoration(color: widget.scrollBarBackgroundColor),
child: Container(
alignment: Alignment.topCenter,
child: GestureDetector(
child: Container(
height: widget.dragHandleHeight,
width: widget.dragHandleWidth,
margin: EdgeInsets.only(left: 5.0, right: 5.0, top: _offset),
decoration: BoxDecoration(
color: widget.dragHandleColor,
borderRadius: BorderRadius.all(
Radius.circular(widget.dragHandleBorderRadius))),
),
onVerticalDragUpdate: (dragUpdate) {
final _towhere = dragUpdate.globalPosition.dy;
_updateScroll(_towhere);
/// Send the new drag details to the callback in order to properly update the scrollable content position
},
),
)));
}
}
Example with fixes:
class _LandingPageState extends State<LandingPage> {
ScrollController _controller;
double _max = 0;
double _screenSize = 0;
@override
void initState() {
//Initialize the scrollController
_controller = ScrollController();
super.initState();
}
void scrollCallBack(double dragUpdate) {
setState(() {
// Note: 3.5 represents the theoretical height of all my scrollable content. This number will vary for you.
_controller.position.moveTo(dragUpdate * _max / _screenSize);
});
}
@override
Widget build(BuildContext context) {
_screenSize = MediaQuery.of(context).size.height;
_max = _controller.hasClients ? _controller.position.maxScrollExtent : 0;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
Container(
child: SingleChildScrollView(
//Assign the controller to my scrollable widget
controller: _controller,
child: Column(
children: [
Container(
``` height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.black,
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.green,
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.blue,
),
],
),
),
),
FlutterWebScroller(
_controller,
//Pass a reference to the ScrollCallBack function into the scrollbar
scrollCallBack,
_max / _screenSize,
//Add optional values
scrollBarBackgroundColor: Colors.white,
scrollBarWidth: 20.0,
dragHandleColor: Colors.red,
dragHandleBorderRadius: 2.0,
dragHandleHeight: 40.0,
dragHandleWidth: 15.0,
),
],
),
);
}
}
When i use the mouse scroll or double finger scroll on the notebook pad, the content scrolls but not the dragHandle
for this implementation i've used the new vars _max and _screensize on the main screen of the example:
class _LandingPageState extends State<LandingPage> {
ScrollController _controller;
double _max = 0;
double _screenSize = 0;
@override
void initState() {
//Initialize the scrollController
_controller = ScrollController();
super.initState();
}
void scrollCallBack(double dragUpdate) {
setState(() {
// Note: 3.5 represents the theoretical height of all my scrollable content. This number will vary for you.
_controller.position.moveTo(dragUpdate * _max / _screenSize);
});
}
@override
Widget build(BuildContext context) {
_screenSize = MediaQuery.of(context).size.height;
_max = _controller.hasClients ? _controller.position.maxScrollExtent : 0;
I've tried changing your code a little to implement this function. Its something like wrapping the container holding the bar with a gesturedetector too:
And changing a little the function:
class _FlutterWebScrollerState extends State<FlutterWebScroller> {
static double _offset = 0;
_updateScroll(double towhere) {
widget.scrollCallBack(towhere);
setState(() {
if (towhere >= 0) {
/// Update the offset of the drag handle to push it down or shift it up
_offset = towhere;
double maxHeight =
MediaQuery.of(context).size.height - widget.dragHandleHeight;
_offset = (_offset > maxHeight) ? maxHeight : _offset;
}
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (TapDownDetails details) =>
_updateScroll(details.globalPosition.dy),
child: Container(
alignment: Alignment.centerRight,
height: MediaQuery.of(context).size.height,
width: widget.scrollBarWidth,
margin: EdgeInsets.only(
left:
MediaQuery.of(context).size.width - widget.scrollBarWidth),
decoration: BoxDecoration(color: widget.scrollBarBackgroundColor),
child: Container(
alignment: Alignment.topCenter,
child: GestureDetector(
child: Container(
height: widget.dragHandleHeight,
width: widget.dragHandleWidth,
margin: EdgeInsets.only(left: 5.0, right: 5.0, top: _offset),
decoration: BoxDecoration(
color: widget.dragHandleColor,
borderRadius: BorderRadius.all(
Radius.circular(widget.dragHandleBorderRadius))),
),
onVerticalDragUpdate: (dragUpdate) {
final _towhere = dragUpdate.globalPosition.dy;
_updateScroll(_towhere);
/// Send the new drag details to the callback in order to properly update the scrollable content position
},
),
)));
}
}
the new scrollcallback on the main screen(on your example):
void scrollCallBack(double dragUpdate) {
setState(() {
// Note: 3.5 represents the theoretical height of all my scrollable content. This number will vary for you.
_controller.position.moveTo(dragUpdate * 3.5);
});
}
The Scrollbar keeps scrolling even when you scroll to the end of the page. It s not so significant for a problem but its an issue.
Thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.