scrollbar_painter.dart 2.92 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:flutter/widgets.dart';

const double _kMinScrollbarThumbLength = 18.0;
const double _kScrollbarThumbGirth = 6.0;
const Duration _kScrollbarThumbFadeDuration = const Duration(milliseconds: 300);

class ScrollbarPainter extends ScrollableListPainter {

  double _opacity = 0.0;
  int get _alpha => (_opacity * 0xFF).round();

  // TODO(hansmuller): thumb color should come from ThemeData.
  Color get thumbColor => const Color(0xFF9E9E9E);

  void paintThumb(PaintingContext context, Rect thumbBounds) {
    final Paint paint = new Paint()..color = thumbColor.withAlpha(_alpha);
    context.canvas.drawRect(thumbBounds, paint);
  }

  void paintScrollbar(PaintingContext context, Offset offset) {
    final Rect viewportBounds = offset & viewportSize;
    Point thumbOrigin;
    Size thumbSize;

31
    switch (scrollDirection) {
32
      case Axis.vertical:
33 34 35 36 37 38 39 40
        double thumbHeight = viewportBounds.height * viewportBounds.height / contentExtent;
        thumbHeight = thumbHeight.clamp(_kMinScrollbarThumbLength, viewportBounds.height);
        final double maxThumbTop = viewportBounds.height - thumbHeight;
        double thumbTop = (scrollOffset / (contentExtent - viewportBounds.height)) * maxThumbTop;
        thumbTop = viewportBounds.top + thumbTop.clamp(0.0, maxThumbTop);
        thumbOrigin = new Point(viewportBounds.right - _kScrollbarThumbGirth, thumbTop);
        thumbSize = new Size(_kScrollbarThumbGirth, thumbHeight);
        break;
41
      case Axis.horizontal:
42 43 44 45 46 47 48 49
        double thumbWidth = viewportBounds.width * viewportBounds.width / contentExtent;
        thumbWidth = thumbWidth.clamp(_kMinScrollbarThumbLength, viewportBounds.width);
        final double maxThumbLeft = viewportBounds.width - thumbWidth;
        double thumbLeft = (scrollOffset / (contentExtent - viewportBounds.width)) * maxThumbLeft;
        thumbLeft = viewportBounds.left + thumbLeft.clamp(0.0, maxThumbLeft);
        thumbOrigin = new Point(thumbLeft, viewportBounds.height - _kScrollbarThumbGirth);
        thumbSize = new Size(thumbWidth, _kScrollbarThumbGirth);
        break;
50 51 52 53 54 55 56 57 58 59 60
    }

    paintThumb(context, thumbOrigin & thumbSize);
  }

  void paint(PaintingContext context, Offset offset) {
    if (_alpha == 0)
      return;
    paintScrollbar(context, offset);
  }

61
  AnimationController _fade;
62 63

  Future scrollStarted() {
64 65 66 67 68
    if (_fade == null) {
      _fade = new AnimationController(duration: _kScrollbarThumbFadeDuration);
      CurvedAnimation curve = new CurvedAnimation(parent: _fade, curve: Curves.ease);
      curve.addListener(() {
        _opacity = curve.value;
69
        renderObject?.markNeedsPaint();
70
      });
71
    }
72 73 74 75 76 77 78 79 80 81 82 83
    return _fade.forward();
  }

  Future scrollEnded() {
    return _fade.reverse();
  }

  void detach() {
    super.detach();
    _fade?.stop();
  }
}