Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
7a4f5ebf
Unverified
Commit
7a4f5ebf
authored
Feb 02, 2022
by
Taha Tesser
Committed by
GitHub
Feb 02, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BottomNavigationBar: add themeable mouse cursor (#96736)
parent
6ceb418b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
81 additions
and
6 deletions
+81
-6
bottom_navigation_bar.dart
packages/flutter/lib/src/material/bottom_navigation_bar.dart
+22
-3
bottom_navigation_bar_theme.dart
...flutter/lib/src/material/bottom_navigation_bar_theme.dart
+13
-2
bottom_navigation_bar_theme_test.dart
...utter/test/material/bottom_navigation_bar_theme_test.dart
+46
-1
No files found.
packages/flutter/lib/src/material/bottom_navigation_bar.dart
View file @
7a4f5ebf
...
@@ -14,6 +14,7 @@ import 'debug.dart';
...
@@ -14,6 +14,7 @@ import 'debug.dart';
import
'ink_well.dart'
;
import
'ink_well.dart'
;
import
'material.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'material_localizations.dart'
;
import
'material_state.dart'
;
import
'theme.dart'
;
import
'theme.dart'
;
import
'tooltip.dart'
;
import
'tooltip.dart'
;
...
@@ -311,9 +312,20 @@ class BottomNavigationBar extends StatefulWidget {
...
@@ -311,9 +312,20 @@ class BottomNavigationBar extends StatefulWidget {
final
bool
?
showSelectedLabels
;
final
bool
?
showSelectedLabels
;
/// The cursor for a mouse pointer when it enters or is hovering over the
/// The cursor for a mouse pointer when it enters or is hovering over the
///
tile
s.
///
item
s.
///
///
/// 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].
///
/// If null, then the value of [BottomNavigationBarThemeData.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
;
final
MouseCursor
?
mouseCursor
;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
/// Whether detected gestures should provide acoustic and/or haptic feedback.
...
@@ -941,10 +953,17 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
...
@@ -941,10 +953,17 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
);
);
break
;
break
;
}
}
final
MouseCursor
effectiveMouseCursor
=
widget
.
mouseCursor
??
SystemMouseCursors
.
click
;
final
List
<
Widget
>
tiles
=
<
Widget
>[];
final
List
<
Widget
>
tiles
=
<
Widget
>[];
for
(
int
i
=
0
;
i
<
widget
.
items
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
widget
.
items
.
length
;
i
++)
{
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
i
==
widget
.
currentIndex
)
MaterialState
.
selected
,
};
final
MouseCursor
effectiveMouseCursor
=
MaterialStateProperty
.
resolveAs
<
MouseCursor
?>(
widget
.
mouseCursor
,
states
)
??
bottomTheme
.
mouseCursor
?.
resolve
(
states
)
??
MaterialStateMouseCursor
.
clickable
.
resolve
(
states
);
tiles
.
add
(
_BottomNavigationTile
(
tiles
.
add
(
_BottomNavigationTile
(
_effectiveType
,
_effectiveType
,
widget
.
items
[
i
],
widget
.
items
[
i
],
...
...
packages/flutter/lib/src/material/bottom_navigation_bar_theme.dart
View file @
7a4f5ebf
...
@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
...
@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import
'package:flutter/widgets.dart'
;
import
'package:flutter/widgets.dart'
;
import
'bottom_navigation_bar.dart'
;
import
'bottom_navigation_bar.dart'
;
import
'material_state.dart'
;
import
'theme.dart'
;
import
'theme.dart'
;
/// Defines default property values for descendant [BottomNavigationBar]
/// Defines default property values for descendant [BottomNavigationBar]
...
@@ -45,6 +46,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -45,6 +46,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
this
.
type
,
this
.
type
,
this
.
enableFeedback
,
this
.
enableFeedback
,
this
.
landscapeLayout
,
this
.
landscapeLayout
,
this
.
mouseCursor
,
});
});
/// The color of the [BottomNavigationBar] itself.
/// The color of the [BottomNavigationBar] itself.
...
@@ -124,6 +126,9 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -124,6 +126,9 @@ class BottomNavigationBarThemeData with Diagnosticable {
/// If non-null, overrides the [BottomNavigationBar.landscapeLayout] property.
/// If non-null, overrides the [BottomNavigationBar.landscapeLayout] property.
final
BottomNavigationBarLandscapeLayout
?
landscapeLayout
;
final
BottomNavigationBarLandscapeLayout
?
landscapeLayout
;
/// If specified, overrides the default value of [BottomNavigationBar.mouseCursor].
final
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
;
/// Creates a copy of this object but with the given fields replaced with the
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
/// new values.
BottomNavigationBarThemeData
copyWith
({
BottomNavigationBarThemeData
copyWith
({
...
@@ -139,7 +144,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -139,7 +144,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
bool
?
showUnselectedLabels
,
bool
?
showUnselectedLabels
,
BottomNavigationBarType
?
type
,
BottomNavigationBarType
?
type
,
bool
?
enableFeedback
,
bool
?
enableFeedback
,
BottomNavigationBarLandscapeLayout
?
landscapeLayout
BottomNavigationBarLandscapeLayout
?
landscapeLayout
,
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
,
})
{
})
{
return
BottomNavigationBarThemeData
(
return
BottomNavigationBarThemeData
(
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
...
@@ -155,6 +161,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -155,6 +161,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
type:
type
??
this
.
type
,
type:
type
??
this
.
type
,
enableFeedback:
enableFeedback
??
this
.
enableFeedback
,
enableFeedback:
enableFeedback
??
this
.
enableFeedback
,
landscapeLayout:
landscapeLayout
??
this
.
landscapeLayout
,
landscapeLayout:
landscapeLayout
??
this
.
landscapeLayout
,
mouseCursor:
mouseCursor
??
this
.
mouseCursor
,
);
);
}
}
...
@@ -179,6 +186,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -179,6 +186,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
type:
t
<
0.5
?
a
?.
type
:
b
?.
type
,
type:
t
<
0.5
?
a
?.
type
:
b
?.
type
,
enableFeedback:
t
<
0.5
?
a
?.
enableFeedback
:
b
?.
enableFeedback
,
enableFeedback:
t
<
0.5
?
a
?.
enableFeedback
:
b
?.
enableFeedback
,
landscapeLayout:
t
<
0.5
?
a
?.
landscapeLayout
:
b
?.
landscapeLayout
,
landscapeLayout:
t
<
0.5
?
a
?.
landscapeLayout
:
b
?.
landscapeLayout
,
mouseCursor:
t
<
0.5
?
a
?.
mouseCursor
:
b
?.
mouseCursor
,
);
);
}
}
...
@@ -198,6 +206,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -198,6 +206,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
type
,
type
,
enableFeedback
,
enableFeedback
,
landscapeLayout
,
landscapeLayout
,
mouseCursor
,
);
);
}
}
...
@@ -220,7 +229,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -220,7 +229,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
&&
other
.
showUnselectedLabels
==
showUnselectedLabels
&&
other
.
showUnselectedLabels
==
showUnselectedLabels
&&
other
.
type
==
type
&&
other
.
type
==
type
&&
other
.
enableFeedback
==
enableFeedback
&&
other
.
enableFeedback
==
enableFeedback
&&
other
.
landscapeLayout
==
landscapeLayout
;
&&
other
.
landscapeLayout
==
landscapeLayout
&&
other
.
mouseCursor
==
mouseCursor
;
}
}
@override
@override
...
@@ -239,6 +249,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
...
@@ -239,6 +249,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
BottomNavigationBarType
>(
'type'
,
type
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
BottomNavigationBarType
>(
'type'
,
type
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'enableFeedback'
,
enableFeedback
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'enableFeedback'
,
enableFeedback
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
BottomNavigationBarLandscapeLayout
>(
'landscapeLayout'
,
landscapeLayout
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
BottomNavigationBarLandscapeLayout
>(
'landscapeLayout'
,
landscapeLayout
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
MouseCursor
?>>(
'mouseCursor'
,
mouseCursor
,
defaultValue:
null
));
}
}
}
}
...
...
packages/flutter/test/material/bottom_navigation_bar_theme_test.dart
View file @
7a4f5ebf
...
@@ -2,8 +2,10 @@
...
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:vector_math/vector_math_64.dart'
show
Vector3
;
import
'package:vector_math/vector_math_64.dart'
show
Vector3
;
...
@@ -28,6 +30,7 @@ void main() {
...
@@ -28,6 +30,7 @@ void main() {
expect
(
themeData
.
showUnselectedLabels
,
null
);
expect
(
themeData
.
showUnselectedLabels
,
null
);
expect
(
themeData
.
type
,
null
);
expect
(
themeData
.
type
,
null
);
expect
(
themeData
.
landscapeLayout
,
null
);
expect
(
themeData
.
landscapeLayout
,
null
);
expect
(
themeData
.
mouseCursor
,
null
);
const
BottomNavigationBarTheme
theme
=
BottomNavigationBarTheme
(
data:
BottomNavigationBarThemeData
(),
child:
SizedBox
());
const
BottomNavigationBarTheme
theme
=
BottomNavigationBarTheme
(
data:
BottomNavigationBarThemeData
(),
child:
SizedBox
());
expect
(
theme
.
data
.
backgroundColor
,
null
);
expect
(
theme
.
data
.
backgroundColor
,
null
);
...
@@ -42,6 +45,7 @@ void main() {
...
@@ -42,6 +45,7 @@ void main() {
expect
(
theme
.
data
.
showUnselectedLabels
,
null
);
expect
(
theme
.
data
.
showUnselectedLabels
,
null
);
expect
(
theme
.
data
.
type
,
null
);
expect
(
theme
.
data
.
type
,
null
);
expect
(
themeData
.
landscapeLayout
,
null
);
expect
(
themeData
.
landscapeLayout
,
null
);
expect
(
themeData
.
mouseCursor
,
null
);
});
});
testWidgets
(
'Default BottomNavigationBarThemeData debugFillProperties'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Default BottomNavigationBarThemeData debugFillProperties'
,
(
WidgetTester
tester
)
async
{
...
@@ -70,6 +74,7 @@ void main() {
...
@@ -70,6 +74,7 @@ void main() {
showSelectedLabels:
true
,
showSelectedLabels:
true
,
showUnselectedLabels:
true
,
showUnselectedLabels:
true
,
type:
BottomNavigationBarType
.
fixed
,
type:
BottomNavigationBarType
.
fixed
,
mouseCursor:
MaterialStateMouseCursor
.
clickable
,
).
debugFillProperties
(
builder
);
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
final
List
<
String
>
description
=
builder
.
properties
...
@@ -93,6 +98,7 @@ void main() {
...
@@ -93,6 +98,7 @@ void main() {
expect
(
description
[
8
],
'showSelectedLabels: true'
);
expect
(
description
[
8
],
'showSelectedLabels: true'
);
expect
(
description
[
9
],
'showUnselectedLabels: true'
);
expect
(
description
[
9
],
'showUnselectedLabels: true'
);
expect
(
description
[
10
],
'type: BottomNavigationBarType.fixed'
);
expect
(
description
[
10
],
'type: BottomNavigationBarType.fixed'
);
expect
(
description
[
11
],
'mouseCursor: MaterialStateMouseCursor(clickable)'
);
});
});
testWidgets
(
'BottomNavigationBar is themeable'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'BottomNavigationBar is themeable'
,
(
WidgetTester
tester
)
async
{
...
@@ -108,7 +114,7 @@ void main() {
...
@@ -108,7 +114,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
theme:
ThemeData
(
theme:
ThemeData
(
bottomNavigationBarTheme:
const
BottomNavigationBarThemeData
(
bottomNavigationBarTheme:
BottomNavigationBarThemeData
(
backgroundColor:
backgroundColor
,
backgroundColor:
backgroundColor
,
selectedItemColor:
selectedItemColor
,
selectedItemColor:
selectedItemColor
,
unselectedItemColor:
unselectedItemColor
,
unselectedItemColor:
unselectedItemColor
,
...
@@ -120,6 +126,12 @@ void main() {
...
@@ -120,6 +126,12 @@ void main() {
type:
BottomNavigationBarType
.
fixed
,
type:
BottomNavigationBarType
.
fixed
,
selectedLabelStyle:
selectedTextStyle
,
selectedLabelStyle:
selectedTextStyle
,
unselectedLabelStyle:
unselectedTextStyle
,
unselectedLabelStyle:
unselectedTextStyle
,
mouseCursor:
MaterialStateProperty
.
resolveWith
<
MouseCursor
?>((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
SystemMouseCursors
.
grab
;
}
return
SystemMouseCursors
.
move
;
}),
),
),
),
),
home:
Scaffold
(
home:
Scaffold
(
...
@@ -166,6 +178,24 @@ void main() {
...
@@ -166,6 +178,24 @@ void main() {
expect
(
findFadeTransition
,
findsNothing
);
expect
(
findFadeTransition
,
findsNothing
);
expect
(
_material
(
tester
).
elevation
,
equals
(
elevation
));
expect
(
_material
(
tester
).
elevation
,
equals
(
elevation
));
expect
(
_material
(
tester
).
color
,
equals
(
backgroundColor
));
expect
(
_material
(
tester
).
color
,
equals
(
backgroundColor
));
final
Offset
selectedBarItem
=
tester
.
getCenter
(
find
.
ancestor
(
of:
find
.
text
(
'AC'
),
matching:
find
.
byType
(
Transform
))
);
final
Offset
unselectedBarItem
=
tester
.
getCenter
(
find
.
ancestor
(
of:
find
.
text
(
'Alarm'
),
matching:
find
.
byType
(
Transform
))
);
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
selectedBarItem
);
await
tester
.
pumpAndSettle
();
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
grab
);
await
gesture
.
moveTo
(
unselectedBarItem
);
await
tester
.
pumpAndSettle
();
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
move
);
});
});
testWidgets
(
'BottomNavigationBar properties are taken over the theme values'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'BottomNavigationBar properties are taken over the theme values'
,
(
WidgetTester
tester
)
async
{
...
@@ -178,6 +208,7 @@ void main() {
...
@@ -178,6 +208,7 @@ void main() {
const
TextStyle
themeUnselectedTextStyle
=
TextStyle
(
fontSize:
21
);
const
TextStyle
themeUnselectedTextStyle
=
TextStyle
(
fontSize:
21
);
const
double
themeElevation
=
9.0
;
const
double
themeElevation
=
9.0
;
const
BottomNavigationBarLandscapeLayout
themeLandscapeLayout
=
BottomNavigationBarLandscapeLayout
.
centered
;
const
BottomNavigationBarLandscapeLayout
themeLandscapeLayout
=
BottomNavigationBarLandscapeLayout
.
centered
;
const
MaterialStateMouseCursor
themeCursor
=
MaterialStateMouseCursor
.
clickable
;
const
Color
backgroundColor
=
Color
(
0xFF000004
);
const
Color
backgroundColor
=
Color
(
0xFF000004
);
const
Color
selectedItemColor
=
Color
(
0xFF000005
);
const
Color
selectedItemColor
=
Color
(
0xFF000005
);
...
@@ -188,6 +219,7 @@ void main() {
...
@@ -188,6 +219,7 @@ void main() {
const
TextStyle
unselectedTextStyle
=
TextStyle
(
fontSize:
26
);
const
TextStyle
unselectedTextStyle
=
TextStyle
(
fontSize:
26
);
const
double
elevation
=
7.0
;
const
double
elevation
=
7.0
;
const
BottomNavigationBarLandscapeLayout
landscapeLayout
=
BottomNavigationBarLandscapeLayout
.
spread
;
const
BottomNavigationBarLandscapeLayout
landscapeLayout
=
BottomNavigationBarLandscapeLayout
.
spread
;
const
MaterialStateMouseCursor
cursor
=
MaterialStateMouseCursor
.
textable
;
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
...
@@ -205,6 +237,7 @@ void main() {
...
@@ -205,6 +237,7 @@ void main() {
selectedLabelStyle:
themeSelectedTextStyle
,
selectedLabelStyle:
themeSelectedTextStyle
,
unselectedLabelStyle:
themeUnselectedTextStyle
,
unselectedLabelStyle:
themeUnselectedTextStyle
,
landscapeLayout:
themeLandscapeLayout
,
landscapeLayout:
themeLandscapeLayout
,
mouseCursor:
themeCursor
,
),
),
),
),
home:
Scaffold
(
home:
Scaffold
(
...
@@ -221,6 +254,7 @@ void main() {
...
@@ -221,6 +254,7 @@ void main() {
selectedLabelStyle:
selectedTextStyle
,
selectedLabelStyle:
selectedTextStyle
,
unselectedLabelStyle:
unselectedTextStyle
,
unselectedLabelStyle:
unselectedTextStyle
,
landscapeLayout:
landscapeLayout
,
landscapeLayout:
landscapeLayout
,
mouseCursor:
cursor
,
items:
const
<
BottomNavigationBarItem
>[
items:
const
<
BottomNavigationBarItem
>[
BottomNavigationBarItem
(
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
ac_unit
),
icon:
Icon
(
Icons
.
ac_unit
),
...
@@ -263,6 +297,17 @@ void main() {
...
@@ -263,6 +297,17 @@ void main() {
expect
(
findFadeTransition
,
findsNothing
);
expect
(
findFadeTransition
,
findsNothing
);
expect
(
_material
(
tester
).
elevation
,
equals
(
elevation
));
expect
(
_material
(
tester
).
elevation
,
equals
(
elevation
));
expect
(
_material
(
tester
).
color
,
equals
(
backgroundColor
));
expect
(
_material
(
tester
).
color
,
equals
(
backgroundColor
));
final
Offset
barItem
=
tester
.
getCenter
(
find
.
ancestor
(
of:
find
.
text
(
'AC'
),
matching:
find
.
byType
(
Transform
))
);
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
barItem
);
await
tester
.
pumpAndSettle
();
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
text
);
});
});
testWidgets
(
'BottomNavigationBarTheme can be used to hide all labels'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'BottomNavigationBarTheme can be used to hide all labels'
,
(
WidgetTester
tester
)
async
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment