TabBar: add themeable mouse cursor (#96737)

This commit is contained in:
Taha Tesser 2022-02-08 02:35:12 +02:00 committed by GitHub
parent 36a8f0f2ae
commit a6504ead31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 3 deletions

View file

@ -37,6 +37,7 @@ class TabBarTheme with Diagnosticable {
this.unselectedLabelStyle,
this.overlayColor,
this.splashFactory,
this.mouseCursor,
});
/// Default value for [TabBar.indicator].
@ -70,6 +71,11 @@ class TabBarTheme with Diagnosticable {
/// Default value for [TabBar.splashFactory].
final InteractiveInkFeatureFactory? splashFactory;
/// {@macro flutter.material.tabs.mouseCursor}
///
/// If specified, overrides the default value of [TabBar.mouseCursor].
final MaterialStateProperty<MouseCursor?>? mouseCursor;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
TabBarTheme copyWith({
@ -82,6 +88,7 @@ class TabBarTheme with Diagnosticable {
TextStyle? unselectedLabelStyle,
MaterialStateProperty<Color?>? overlayColor,
InteractiveInkFeatureFactory? splashFactory,
MaterialStateProperty<MouseCursor?>? mouseCursor,
}) {
return TabBarTheme(
indicator: indicator ?? this.indicator,
@ -93,6 +100,7 @@ class TabBarTheme with Diagnosticable {
unselectedLabelStyle: unselectedLabelStyle ?? this.unselectedLabelStyle,
overlayColor: overlayColor ?? this.overlayColor,
splashFactory: splashFactory ?? this.splashFactory,
mouseCursor: mouseCursor ?? this.mouseCursor,
);
}
@ -120,6 +128,7 @@ class TabBarTheme with Diagnosticable {
unselectedLabelStyle: TextStyle.lerp(a.unselectedLabelStyle, b.unselectedLabelStyle, t),
overlayColor: _LerpColors(a.overlayColor, b.overlayColor, t),
splashFactory: t < 0.5 ? a.splashFactory : b.splashFactory,
mouseCursor: t < 0.5 ? a.mouseCursor : b.mouseCursor,
);
}
@ -135,6 +144,7 @@ class TabBarTheme with Diagnosticable {
unselectedLabelStyle,
overlayColor,
splashFactory,
mouseCursor,
);
}
@ -153,7 +163,8 @@ class TabBarTheme with Diagnosticable {
&& other.unselectedLabelColor == unselectedLabelColor
&& other.unselectedLabelStyle == unselectedLabelStyle
&& other.overlayColor == overlayColor
&& other.splashFactory == splashFactory;
&& other.splashFactory == splashFactory
&& other.mouseCursor == mouseCursor;
}
}

View file

@ -803,10 +803,23 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
/// {@macro flutter.widgets.scrollable.dragStartBehavior}
final DragStartBehavior dragStartBehavior;
/// {@template flutter.material.tabs.mouseCursor}
/// The cursor for a mouse pointer when it enters or is hovering over the
/// individual tab widgets.
///
/// If this property is null, [SystemMouseCursors.click] will be used.
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
/// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
///
/// * [MaterialState.selected].
/// {@endtemplate}
///
/// If null, then the value of [TabBarTheme.mouseCursor] is used. If
/// that is also null, then [MaterialStateMouseCursor.clickable] is used.
///
/// See also:
///
/// * [MaterialStateMouseCursor], which can be used to create a [MouseCursor]
/// that is also a [MaterialStateProperty<MouseCursor>].
final MouseCursor? mouseCursor;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
@ -1222,8 +1235,16 @@ class _TabBarState extends State<TabBar> {
// the same share of the tab bar's overall width.
final int tabCount = widget.tabs.length;
for (int index = 0; index < tabCount; index += 1) {
final Set<MaterialState> states = <MaterialState>{
if (index == _currentIndex) MaterialState.selected,
};
final MouseCursor effectiveMouseCursor = MaterialStateProperty.resolveAs<MouseCursor?>(widget.mouseCursor, states)
?? tabBarTheme.mouseCursor?.resolve(states)
?? MaterialStateMouseCursor.clickable.resolve(states);
wrappedTabs[index] = InkWell(
mouseCursor: widget.mouseCursor ?? SystemMouseCursors.click,
mouseCursor: effectiveMouseCursor,
onTap: () { _handleTap(index); },
enableFeedback: widget.enableFeedback ?? true,
overlayColor: widget.overlayColor ?? tabBarTheme.overlayColor,

View file

@ -6,6 +6,7 @@
// machines.
@Tags(<String>['reduced-test-set'])
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
@ -67,6 +68,7 @@ void main() {
expect(const TabBarTheme().unselectedLabelStyle, null);
expect(const TabBarTheme().overlayColor, null);
expect(const TabBarTheme().splashFactory, null);
expect(const TabBarTheme().mouseCursor, null);
});
testWidgets('Tab bar defaults - label style and selected/unselected label colors', (WidgetTester tester) async {
@ -302,6 +304,22 @@ void main() {
);
});
testWidgets('Tab bar theme overrides tab mouse cursor', (WidgetTester tester) async {
const TabBarTheme tabBarTheme = TabBarTheme(mouseCursor: MaterialStateMouseCursor.textable);
await tester.pumpWidget(_withTheme(tabBarTheme));
final Offset tabBar = tester.getCenter(
find.ancestor(of: find.text('tab 1'),matching: find.byType(TabBar)),
);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
addTearDown(gesture.removePointer);
await gesture.moveTo(tabBar);
await tester.pumpAndSettle();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
});
testWidgets('Tab bar theme - custom tab indicator', (WidgetTester tester) async {
final TabBarTheme tabBarTheme = TabBarTheme(
indicator: BoxDecoration(