flutter_flutter/sdk/lib/framework/components2/fixed_height_scrollable.dart
Hixie 003083a12d Remove one more use of mirrors: Components now have to explicitly sync their fields.
This also removes one bit of magic to make it more obvious what on is
going on during a sync, which should hopefully help.

Components have to decide if they support being stateful or not. If
they do, then they must implement syncFields() and have mutable
fields; if they don't, then they must have final fields. This isn't
particularly enforced, though.

This also renames _willSync() to _retainStatefulNodeIfPossible(), for
clarity, and fixes some minor style issues and one typo that was
breaking the drawer.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1174023003
2015-06-10 10:33:04 -07:00

89 lines
2.4 KiB
Dart

// 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 '../animation/scroll_behavior.dart';
import '../fn2.dart';
import 'dart:async';
import 'dart:math' as math;
import 'package:vector_math/vector_math.dart';
import 'scrollable.dart';
abstract class FixedHeightScrollable extends Scrollable {
FixedHeightScrollable({ this.itemHeight, Object key }) : super(key: key) {
assert(itemHeight != null);
}
double itemHeight;
void syncFields(FixedHeightScrollable source) {
itemHeight = source.itemHeight;
super.syncFields(source);
}
ScrollBehavior createScrollBehavior() => new OverscrollBehavior();
OverscrollBehavior get scrollBehavior => super.scrollBehavior as OverscrollBehavior;
int _itemCount = 0;
int get itemCount => _itemCount;
void set itemCount (int value) {
if (_itemCount != value) {
_itemCount = value;
scrollBehavior.contentsHeight = itemHeight * _itemCount;
}
}
double _height;
void _handleSizeChanged(Size newSize) {
setState(() {
_height = newSize.height;
scrollBehavior.containerHeight = _height;
});
}
UINode buildContent() {
var itemShowIndex = 0;
var itemShowCount = 0;
Matrix4 transform = new Matrix4.identity();
if (_height != null && _height > 0.0) {
if (scrollOffset < 0.0) {
double visibleHeight = _height + scrollOffset;
itemShowCount = (visibleHeight / itemHeight).round() + 1;
transform.translate(0.0, -scrollOffset);
} else {
itemShowCount = (_height / itemHeight).ceil() + 1;
double alignmentDelta = -scrollOffset % itemHeight;
if (alignmentDelta != 0.0)
alignmentDelta -= itemHeight;
double drawStart = scrollOffset + alignmentDelta;
itemShowIndex = math.max(0, (drawStart / itemHeight).floor());
transform.translate(0.0, alignmentDelta);
}
}
return new SizeObserver(
callback: _handleSizeChanged,
child: new Clip(
child: new DecoratedBox(
decoration: const BoxDecoration(
backgroundColor: const Color(0xFFFFFFFF)
),
child: new Transform(
transform: transform,
child: new BlockContainer(
children: buildItems(itemShowIndex, itemShowCount))
)
)
)
);
}
List<UINode> buildItems(int start, int count);
}