scrollbar_painter.dart 3 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 31 32
// 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/animation.dart';
import 'package:flutter/rendering.dart';
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;

33
    switch (scrollDirection) {
34
      case Axis.vertical:
35 36 37 38 39 40 41 42
        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;
43
      case Axis.horizontal:
44 45 46 47 48 49 50 51
        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;
52 53 54 55 56 57 58 59 60 61 62
    }

    paintThumb(context, thumbOrigin & thumbSize);
  }

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

63
  AnimationController _fade;
64 65

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

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

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