Commit f0354b82 authored by Christian Mürtz's avatar Christian Mürtz Committed by Shi-Hao Hong

Add CheckboxListTile checkColor (#37636)

* Add checkColor to CheckboxListTile

* Create second paint for drawing check and dash

* Add activeColor test for Checkbox
Co-Authored-By: 's avatarShi-Hao Hong <shihaohong@google.com>
parent 50193212
......@@ -104,7 +104,7 @@ class Checkbox extends StatefulWidget {
/// Defaults to [ThemeData.toggleableActiveColor].
final Color activeColor;
/// The color to use for the check icon when this checkbox is checked
/// The color to use for the check icon when this checkbox is checked.
///
/// Defaults to Color(0xFFFFFFFF)
final Color checkColor;
......@@ -281,8 +281,8 @@ class _RenderCheckbox extends RenderToggleable {
}
// White stroke used to paint the check and dash.
void _initStrokePaint(Paint paint) {
paint
Paint _createStrokePaint() {
return Paint()
..color = checkColor
..style = PaintingStyle.stroke
..strokeWidth = _kStrokeWidth;
......@@ -336,6 +336,7 @@ class _RenderCheckbox extends RenderToggleable {
final Canvas canvas = context.canvas;
paintRadialReaction(canvas, offset, size.center(Offset.zero));
final Paint strokePaint = _createStrokePaint();
final Offset origin = offset + (size / 2.0 - const Size.square(_kEdgeSize) / 2.0);
final AnimationStatus status = position.status;
final double tNormalized = status == AnimationStatus.forward || status == AnimationStatus.completed
......@@ -353,31 +354,29 @@ class _RenderCheckbox extends RenderToggleable {
} else {
canvas.drawRRect(outer, paint);
_initStrokePaint(paint);
final double tShrink = (t - 0.5) * 2.0;
if (_oldValue == null || value == null)
_drawDash(canvas, origin, tShrink, paint);
_drawDash(canvas, origin, tShrink, strokePaint);
else
_drawCheck(canvas, origin, tShrink, paint);
_drawCheck(canvas, origin, tShrink, strokePaint);
}
} else { // Two cases: null to true, true to null
final RRect outer = _outerRectAt(origin, 1.0);
final Paint paint = Paint() ..color = _colorAt(1.0);
canvas.drawRRect(outer, paint);
_initStrokePaint(paint);
if (tNormalized <= 0.5) {
final double tShrink = 1.0 - tNormalized * 2.0;
if (_oldValue == true)
_drawCheck(canvas, origin, tShrink, paint);
_drawCheck(canvas, origin, tShrink, strokePaint);
else
_drawDash(canvas, origin, tShrink, paint);
_drawDash(canvas, origin, tShrink, strokePaint);
} else {
final double tExpand = (tNormalized - 0.5) * 2.0;
if (value == true)
_drawCheck(canvas, origin, tExpand, paint);
_drawCheck(canvas, origin, tExpand, strokePaint);
else
_drawDash(canvas, origin, tExpand, paint);
_drawDash(canvas, origin, tExpand, strokePaint);
}
}
}
......
......@@ -17,7 +17,7 @@ import 'theme_data.dart';
/// The entire list tile is interactive: tapping anywhere in the tile toggles
/// the checkbox.
///
/// The [value], [onChanged], and [activeColor] properties of this widget are
/// The [value], [onChanged], [activeColor] and [checkColor] properties of this widget are
/// identical to the similarly-named properties on the [Checkbox] widget.
///
/// The [title], [subtitle], [isThreeLine], and [dense] properties are like
......@@ -268,6 +268,7 @@ class CheckboxListTile extends StatelessWidget {
@required this.value,
@required this.onChanged,
this.activeColor,
this.checkColor,
this.title,
this.subtitle,
this.isThreeLine = false,
......@@ -317,6 +318,11 @@ class CheckboxListTile extends StatelessWidget {
/// Defaults to accent color of the current [Theme].
final Color activeColor;
/// The color to use for the check icon when this checkbox is checked.
///
/// Defaults to Color(0xFFFFFFFF).
final Color checkColor;
/// The primary content of the list tile.
///
/// Typically a [Text] widget.
......@@ -361,6 +367,7 @@ class CheckboxListTile extends StatelessWidget {
value: value,
onChanged: onChanged,
activeColor: activeColor,
checkColor: checkColor,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
);
Widget leading, trailing;
......
// Copyright 2019 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_test/flutter_test.dart';
import 'package:flutter/material.dart';
import '../rendering/mock_canvas.dart';
Widget wrap({ Widget child }) {
return MediaQuery(
data: const MediaQueryData(),
child: Directionality(
textDirection: TextDirection.ltr,
child: Material(child: child),
),
);
}
void main() {
testWidgets('CheckboxListTile control test', (WidgetTester tester) async {
final List<dynamic> log = <dynamic>[];
await tester.pumpWidget(wrap(
child: CheckboxListTile(
value: true,
onChanged: (bool value) { log.add(value); },
title: const Text('Hello'),
),
));
await tester.tap(find.text('Hello'));
log.add('-');
await tester.tap(find.byType(Checkbox));
expect(log, equals(<dynamic>[false, '-', false]));
});
testWidgets('CheckboxListTile checkColor test', (WidgetTester tester) async {
Widget buildFrame(Color color) {
return wrap(
child: CheckboxListTile(
value: true,
checkColor: color,
onChanged: (bool value) {},
),
);
}
RenderBox getCheckboxListTileRenderer() {
return tester.renderObject<RenderBox>(find.byType(CheckboxListTile));
}
await tester.pumpWidget(buildFrame(null));
await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFFFFFFFF))); // paints's color is 0xFFFFFFFF (default color)
await tester.pumpWidget(buildFrame(const Color(0xFF000000)));
await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (params)
});
testWidgets('CheckboxListTile activeColor test', (WidgetTester tester) async {
Widget buildFrame(Color themeColor, Color activeColor) {
return wrap(
child: Theme(
data: ThemeData(toggleableActiveColor: themeColor),
child: CheckboxListTile(
value: true,
activeColor: activeColor,
onChanged: (bool value) {},
),
),
);
}
RenderBox getCheckboxListTileRenderer() {
return tester.renderObject<RenderBox>(find.byType(CheckboxListTile));
}
await tester.pumpWidget(buildFrame(const Color(0xFF000000), null));
await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..rrect(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (theme)
await tester.pumpWidget(buildFrame(const Color(0xFF000000), const Color(0xFFFFFFFF)));
await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..rrect(color: const Color(0xFFFFFFFF))); // paints's color is 0xFFFFFFFF (params)
});
}
......@@ -337,17 +337,21 @@ void main() {
});
testWidgets('CheckBox color rendering', (WidgetTester tester) async {
Widget buildFrame(Color color) {
Widget buildFrame({Color activeColor, Color checkColor, ThemeData themeData}) {
return Material(
child: Theme(
data: themeData ?? ThemeData(),
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Checkbox(
value: true,
checkColor: color,
activeColor: activeColor,
checkColor: checkColor,
onChanged: (bool value) { },
);
},
),
),
);
}
......@@ -355,13 +359,21 @@ void main() {
return tester.renderObject<RenderToggleable>(find.byType(Checkbox));
}
await tester.pumpWidget(buildFrame(null));
await tester.pumpWidget(buildFrame(checkColor: const Color(0xFFFFFFFF)));
await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..path(color: const Color(0xFFFFFFFF))); // paints's color is 0xFFFFFFFF (default color)
await tester.pumpWidget(buildFrame(const Color(0xFF000000)));
await tester.pumpWidget(buildFrame(checkColor: const Color(0xFF000000)));
await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..path(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (params)
await tester.pumpWidget(buildFrame(themeData: ThemeData(toggleableActiveColor: const Color(0xFF00FF00))));
await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: const Color(0xFF00FF00))); // paints's color is 0xFF00FF00 (theme)
await tester.pumpWidget(buildFrame(activeColor: const Color(0xFF000000)));
await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (params)
});
}
......@@ -19,21 +19,6 @@ Widget wrap({ Widget child }) {
}
void main() {
testWidgets('CheckboxListTile control test', (WidgetTester tester) async {
final List<dynamic> log = <dynamic>[];
await tester.pumpWidget(wrap(
child: CheckboxListTile(
value: true,
onChanged: (bool value) { log.add(value); },
title: const Text('Hello'),
),
));
await tester.tap(find.text('Hello'));
log.add('-');
await tester.tap(find.byType(Checkbox));
expect(log, equals(<dynamic>[false, '-', false]));
});
testWidgets('RadioListTile should initialize according to groupValue', (WidgetTester tester) async {
final List<int> values = <int>[0, 1, 2];
int selectedValue;
......
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