Add RTL support to Scrollbar (#11843)

When scrolling vertically, the scrollbar is on the left in RTL.
This commit is contained in:
Adam Barth 2017-08-30 10:04:07 -07:00 committed by GitHub
parent 268ec4b374
commit d4e52ccb7e
4 changed files with 69 additions and 26 deletions

View file

@ -49,7 +49,9 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
void didChangeDependencies() {
super.didChangeDependencies();
_painter ??= new _ScrollbarPainter(this);
_painter.color = Theme.of(context).highlightColor;
_painter
..color = Theme.of(context).highlightColor
..textDirection = Directionality.of(context);
}
bool _handleScrollNotification(ScrollNotification notification) {
@ -102,12 +104,22 @@ class _ScrollbarPainter extends ChangeNotifier implements CustomPainter {
Color _color;
set color(Color value) {
assert(value != null);
if (color == value)
if (_color == value)
return;
_color = value;
notifyListeners();
}
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
set textDirection(TextDirection value) {
assert(value != null);
if (_textDirection == value)
return;
_textDirection = value;
notifyListeners();
}
@override
void dispose() {
_fadeOut?.cancel();
@ -142,8 +154,19 @@ class _ScrollbarPainter extends ChangeNotifier implements CustomPainter {
Paint get _paint => new Paint()..color = color.withOpacity(_opacity.value);
double _getThumbX(Size size) {
assert(textDirection != null);
switch (textDirection) {
case TextDirection.rtl:
return 0.0;
case TextDirection.ltr:
return size.width - _kThumbGirth;
}
return null;
}
void _paintVerticalThumb(Canvas canvas, Size size, double thumbOffset, double thumbExtent) {
final Offset thumbOrigin = new Offset(size.width - _kThumbGirth, thumbOffset);
final Offset thumbOrigin = new Offset(_getThumbX(size), thumbOffset);
final Size thumbSize = new Size(_kThumbGirth, thumbExtent);
canvas.drawRect(thumbOrigin & thumbSize, _paint);
}

View file

@ -8,14 +8,31 @@ import 'package:flutter/material.dart';
import '../rendering/mock_canvas.dart';
void main() {
testWidgets('Viewport basic test', (WidgetTester tester) async {
await tester.pumpWidget(new Scrollbar(
child: new SingleChildScrollView(
child: const SizedBox(width: 4000.0, height: 4000.0),
testWidgets('Viewport basic test (LTR)', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Scrollbar(
child: new SingleChildScrollView(
child: const SizedBox(width: 4000.0, height: 4000.0),
),
),
));
expect(find.byType(Scrollbar), isNot(paints..rect()));
await tester.fling(find.byType(SingleChildScrollView), const Offset(0.0, -10.0), 10.0);
expect(find.byType(Scrollbar), paints..rect());
expect(find.byType(Scrollbar), paints..rect(rect: new Rect.fromLTRB(800.0 - 6.0, 1.5, 800.0, 91.5)));
});
testWidgets('Viewport basic test (RTL)', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.rtl,
child: new Scrollbar(
child: new SingleChildScrollView(
child: const SizedBox(width: 4000.0, height: 4000.0),
),
),
));
expect(find.byType(Scrollbar), isNot(paints..rect()));
await tester.fling(find.byType(SingleChildScrollView), const Offset(0.0, -10.0), 10.0);
expect(find.byType(Scrollbar), paints..rect(rect: new Rect.fromLTRB(0.0, 1.5, 6.0, 91.5)));
});
}

View file

@ -19,8 +19,9 @@ class TestCanvas implements Canvas {
void main() {
testWidgets('Scrollbar doesn\'t show when tapping list', (WidgetTester tester) async {
await tester.pumpWidget(
new Center(
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Center(
child: new Container(
decoration: new BoxDecoration(
border: new Border.all(color: const Color(0xFFFFFF00))
@ -38,12 +39,12 @@ void main() {
new Container(height: 40.0, child: const Text('5')),
new Container(height: 40.0, child: const Text('6')),
new Container(height: 40.0, child: const Text('7')),
]
)
)
)
)
);
],
),
),
),
),
));
SchedulerBinding.instance.debugAssertNoTransientCallbacks('Building a list with a scrollbar triggered an animation.');
await tester.tap(find.byType(ListView));
@ -61,19 +62,20 @@ void main() {
});
testWidgets('ScrollbarPainter does not divide by zero', (WidgetTester tester) async {
await tester.pumpWidget(
new Container(
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Container(
height: 200.0,
width: 300.0,
child: new Scrollbar(
child: new ListView(
children: <Widget>[
new Container(height: 40.0, child: const Text('0')),
]
)
)
)
);
],
),
),
),
));
final CustomPaint custom = tester.widget(find.descendant(of: find.byType(Scrollbar), matching: find.byType(CustomPaint)).first);
final dynamic scrollPainter = custom.foregroundPainter;

View file

@ -73,8 +73,9 @@ class TestViewportScrollPosition extends ScrollPositionWithSingleContext {
void main() {
testWidgets('Evil test of sliver features - 1', (WidgetTester tester) async {
final GlobalKey centerKey = new GlobalKey();
await tester.pumpWidget(
new ScrollConfiguration(
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new ScrollConfiguration(
behavior: new TestBehavior(),
child: new Scrollbar(
child: new Scrollable(
@ -159,7 +160,7 @@ void main() {
),
),
),
);
));
final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
position.animateTo(10000.0, curve: Curves.linear, duration: const Duration(minutes: 1));