Commit 0c42c9b1 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add CupertinoActivityIndicator (#7380)

Fixes #7372
parent b40f0cae
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
/// To use, import `package:flutter/cupertino.dart`. /// To use, import `package:flutter/cupertino.dart`.
library cupertino; library cupertino;
export 'src/cupertino/activity_indicator.dart';
export 'src/cupertino/slider.dart'; export 'src/cupertino/slider.dart';
export 'src/cupertino/switch.dart'; export 'src/cupertino/switch.dart';
export 'src/cupertino/thumb_painter.dart'; export 'src/cupertino/thumb_painter.dart';
// Copyright 2017 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:math' as math;
import 'package:flutter/widgets.dart';
/// An iOS-style activity indicator.
///
/// See also:
///
/// * <https://developer.apple.com/ios/human-interface-guidelines/ui-controls/progress-indicators/#activity-indicators>
class CupertinoActivityIndicator extends StatefulWidget {
/// Creates an iOS-style activity indicator.
CupertinoActivityIndicator({
Key key,
this.animating: true,
}) : super(key: key) {
assert(animating != null);
}
/// Whether the activity indicator is running its animation.
///
/// Defaults to true.
final bool animating;
@override
_CupertinoActivityIndicatorState createState() => new _CupertinoActivityIndicatorState();
}
const double _kIndicatorWidth = 20.0;
const double _kIndicatorHeight = 20.0;
class _CupertinoActivityIndicatorState extends State<CupertinoActivityIndicator> with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = new AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
);
if (config.animating)
_controller.repeat();
}
@override
void didUpdateConfig(CupertinoActivityIndicator oldConfig) {
if (config.animating != oldConfig.animating) {
if (config.animating)
_controller.repeat();
else
_controller.stop();
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new SizedBox(
width: _kIndicatorWidth,
height: _kIndicatorHeight,
child: new CustomPaint(
painter: new _CupertinoActivityIndicatorPainter(
position: _controller,
),
),
);
}
}
const double _kTwoPI = math.PI * 2.0;
const int _kTickCount = 12;
const int _kHalfTickCount = _kTickCount ~/ 2;
const Color _kTickColor = const Color(0xFFE0E0E0);
const Color _kActiveTickColor = const Color(0xFF9D9D9D);
final RRect _kTickFundamentalRRect = new RRect.fromLTRBXY(-10.0, 1.0, -5.0, -1.0, 1.0, 1.0);
class _CupertinoActivityIndicatorPainter extends CustomPainter {
_CupertinoActivityIndicatorPainter({
Animation<double> position,
}) : position = position, super(repaint: position);
final Animation<double> position;
@override
void paint(Canvas canvas, Size size) {
final Paint paint = new Paint();
canvas.save();
canvas.translate(size.width / 2.0, size.height / 2.0);
final int activeTick = (_kTickCount * position.value).floor();
for (int i = 0; i < _kTickCount; ++ i) {
final double t = (((i + activeTick) % _kTickCount) / _kHalfTickCount).clamp(0.0, 1.0);
paint.color = Color.lerp(_kActiveTickColor, _kTickColor, t);
canvas.drawRRect(_kTickFundamentalRRect, paint);
canvas.rotate(-_kTwoPI / _kTickCount);
}
canvas.restore();
}
@override
bool shouldRepaint(_CupertinoActivityIndicatorPainter oldPainter) {
return oldPainter.position != position;
}
}
// Copyright 2017 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 'package:flutter/cupertino.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Activity indicator animate property works', (WidgetTester tester) async {
await tester.pumpWidget(new Center(child: new CupertinoActivityIndicator()));
expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
await tester.pumpWidget(new Center(child: new CupertinoActivityIndicator(animating: false)));
expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
await tester.pumpWidget(new Container());
await tester.pumpWidget(new Center(child: new CupertinoActivityIndicator(animating: false)));
expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
await tester.pumpWidget(new Center(child: new CupertinoActivityIndicator()));
expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment