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
3f32201c
Commit
3f32201c
authored
Dec 21, 2015
by
Hans Muller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
checkpoint
parent
95b50915
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
171 additions
and
102 deletions
+171
-102
tabs.dart
packages/flutter/lib/src/material/tabs.dart
+171
-102
No files found.
packages/flutter/lib/src/material/tabs.dart
View file @
3f32201c
...
...
@@ -381,24 +381,61 @@ class _TabsScrollBehavior extends BoundedBehavior {
}
}
class
TabBarSelection
{
TabBarSelection
({
int
index:
0
,
this
.
maxIndex
,
this
.
onChanged
})
:
_index
=
index
{
class
_TabBarSelection
extends
InheritedWidget
{
_TabBarSelection
({
this
.
selection
,
Key
key
,
Widget
child
})
:
super
(
key:
key
,
child:
child
);
final
TabBarSelectionState
selection
;
bool
updateShouldNotify
(
_TabBarSelection
oldWidget
)
=>
selection
!=
oldWidget
.
selection
;
}
class
TabBarSelection
extends
StatefulComponent
{
TabBarSelection
({
Key
key
,
this
.
index
:
0
,
this
.
maxIndex
,
this
.
onChanged
,
Widget
this
.
child
})
{
assert
(
maxIndex
!=
null
);
assert
(
index
!=
null
);
assert
(
_index
>=
0
&&
_
index
<=
maxIndex
);
assert
(
index
>=
0
&&
index
<=
maxIndex
);
}
final
VoidCallback
onChanged
;
final
int
index
;
// TBD: this doesn't work yet...
final
int
maxIndex
;
final
Widget
child
;
final
ValueChanged
<
int
>
onChanged
;
TabBarSelectionState
createState
()
=>
new
TabBarSelectionState
();
static
TabBarSelectionState
of
(
BuildContext
context
)
{
_TabBarSelection
widget
=
context
.
inheritFromWidgetOfType
(
_TabBarSelection
);
return
widget
?.
selection
;
}
}
class
TabBarSelectionState
extends
State
<
TabBarSelection
>
{
// Both the TabBar and TabBarView classes access _performance because they
// alternately drive selection progress between tabs.
PerformanceView
get
performance
=>
_performance
.
view
;
final
_performance
=
new
Performance
(
duration:
_kTabBarScroll
,
progress:
1.0
);
void
dispose
()
{
_performance
.
stop
();
super
.
dispose
();
}
bool
_indexIsChanging
=
false
;
bool
get
indexIsChanging
=>
_indexIsChanging
;
int
get
index
=>
_index
;
int
_index
;
int
_index
=
0
;
void
set
index
(
int
value
)
{
if
(
value
==
_index
)
return
;
...
...
@@ -422,7 +459,7 @@ class TabBarSelection {
progress
=
0.0
;
else
if
(
_previousIndex
==
0
)
progress
=
_performance
.
progress
;
else
if
(
_previousIndex
==
maxIndex
)
else
if
(
_previousIndex
==
config
.
maxIndex
)
progress
=
1.0
-
_performance
.
progress
;
else
if
(
_previousIndex
<
_index
)
progress
=
(
_performance
.
progress
-
0.5
)
*
2.0
;
...
...
@@ -432,62 +469,76 @@ class TabBarSelection {
_performance
..
progress
=
progress
..
forward
().
then
((
_
)
{
if
(
onChanged
!=
null
)
onChanged
(
);
if
(
config
.
onChanged
!=
null
)
config
.
onChanged
(
_index
);
_indexIsChanging
=
false
;
});
}
int
get
previousIndex
=>
_previousIndex
;
int
_previousIndex
=
0
;
Widget
build
(
BuildContext
context
)
{
return
new
_TabBarSelection
(
selection:
this
,
child:
config
.
child
);
}
}
/// A tab strip, consisting of several TabLabels and a TabBarSelection.
/// The TabBarSelection can be used to link this to a TabBarView.
/// Displays a horizontal row of tabs, one per label. If isScrollable is
/// true then each tab is as wide as needed for its label and the entire
/// [TabBar] is scrollable. Otherwise each tab gets an equal share of the
/// available space. A [TabBarSelection] widget ancestor must have been
/// built to enable saving and monitoring the selected tab.
///
/// Tabs must always have an ancestor Material object.
class
TabBar
extends
Scrollable
{
TabBar
({
Key
key
,
this
.
labels
,
this
.
selection
,
this
.
isScrollable
:
false
})
:
super
(
key:
key
,
scrollDirection:
ScrollDirection
.
horizontal
)
{
assert
(
labels
!=
null
);
assert
(
labels
.
length
>
1
);
assert
(
selection
!=
null
);
assert
(
selection
.
maxIndex
==
labels
.
length
-
1
);
}
final
Iterable
<
TabLabel
>
labels
;
final
TabBarSelection
selection
;
final
bool
isScrollable
;
_TabBarState
createState
()
=>
new
_TabBarState
();
}
class
_TabBarState
extends
ScrollableState
<
TabBar
>
{
void
initState
()
{
super
.
initState
();
scrollBehavior
.
isScrollable
=
config
.
isScrollable
;
config
.
selection
.
_performance
TabBarSelectionState
_selection
;
bool
_indexIsChanging
=
false
;
int
get
_tabCount
=>
config
.
labels
.
length
;
void
_addSelectionListeners
(
TabBarSelectionState
selection
)
{
if
(
selection
!=
null
)
{
selection
.
_performance
..
addStatusListener
(
_handleStatusChange
)
..
addListener
(
_handleProgressChange
);
}
}
void
dispose
()
{
config
.
selection
.
_performance
void
_removeSelectionListeners
(
TabBarSelectionState
selection
)
{
if
(
selection
!=
null
)
{
selection
.
_performance
..
removeStatusListener
(
_handleStatusChange
)
..
removeListener
(
_handleProgressChange
)
..
stop
();
super
.
dispose
();
..
removeListener
(
_handleProgressChange
);
}
}
Performance
get
_performance
=>
config
.
selection
.
_performance
;
int
get
_tabCount
=>
config
.
labels
.
length
;
void
initState
()
{
super
.
initState
();
scrollBehavior
.
isScrollable
=
config
.
isScrollable
;
}
bool
_indexIsChanging
=
false
;
void
dispose
()
{
_removeSelectionListeners
(
_selection
);
super
.
dispose
();
}
void
_handleStatusChange
(
PerformanceStatus
status
)
{
if
(
_tabCount
==
0
)
...
...
@@ -496,14 +547,14 @@ class _TabBarState extends ScrollableState<TabBar> {
if
(
_indexIsChanging
&&
status
==
PerformanceStatus
.
completed
)
{
_indexIsChanging
=
false
;
double
progress
=
0.5
;
if
(
config
.
selection
.
index
==
0
)
if
(
_
selection
.
index
==
0
)
progress
=
0.0
;
else
if
(
config
.
selection
.
index
==
_tabCount
-
1
)
else
if
(
_
selection
.
index
==
_tabCount
-
1
)
progress
=
1.0
;
setState
(()
{
_indicatorRect
..
begin
=
_tabIndicatorRect
(
math
.
max
(
0
,
config
.
selection
.
index
-
1
))
..
end
=
_tabIndicatorRect
(
math
.
min
(
_tabCount
-
1
,
config
.
selection
.
index
+
1
))
..
begin
=
_tabIndicatorRect
(
math
.
max
(
0
,
_
selection
.
index
-
1
))
..
end
=
_tabIndicatorRect
(
math
.
min
(
_tabCount
-
1
,
_
selection
.
index
+
1
))
..
curve
=
null
..
setProgress
(
progress
,
AnimationDirection
.
forward
);
});
...
...
@@ -511,20 +562,20 @@ class _TabBarState extends ScrollableState<TabBar> {
}
void
_handleProgressChange
()
{
if
(
_tabCount
==
0
)
if
(
_tabCount
==
0
||
_selection
==
null
)
return
;
if
(!
_indexIsChanging
&&
config
.
selection
.
indexIsChanging
)
{
if
(!
_indexIsChanging
&&
_
selection
.
indexIsChanging
)
{
if
(
config
.
isScrollable
)
scrollTo
(
_centeredTabScrollOffset
(
config
.
selection
.
index
),
duration:
_kTabBarScroll
);
scrollTo
(
_centeredTabScrollOffset
(
_
selection
.
index
),
duration:
_kTabBarScroll
);
_indicatorRect
..
begin
=
_indicatorRect
.
value
??
_tabIndicatorRect
(
config
.
selection
.
previousIndex
)
..
end
=
_tabIndicatorRect
(
config
.
selection
.
index
)
..
begin
=
_indicatorRect
.
value
??
_tabIndicatorRect
(
_
selection
.
previousIndex
)
..
end
=
_tabIndicatorRect
(
_
selection
.
index
)
..
curve
=
Curves
.
ease
;
_indexIsChanging
=
true
;
}
setState
(()
{
_indicatorRect
.
setProgress
(
_performance
.
progress
,
AnimationDirection
.
forward
);
_indicatorRect
.
setProgress
(
_
selection
.
performance
.
progress
,
AnimationDirection
.
forward
);
});
}
...
...
@@ -568,21 +619,24 @@ class _TabBarState extends ScrollableState<TabBar> {
}
void
_handleTabSelected
(
int
tabIndex
)
{
if
(
tabIndex
!=
config
.
selection
.
index
)
if
(
_selection
!=
null
&&
tabIndex
!=
_
selection
.
index
)
setState
(()
{
config
.
selection
.
index
=
tabIndex
;
_
selection
.
index
=
tabIndex
;
});
}
Widget
_toTab
(
TabLabel
label
,
int
tabIndex
,
Color
color
,
Color
selectedColor
)
{
final
bool
isSelectedTab
=
tabIndex
==
config
.
selection
.
index
;
final
bool
isPreviouslySelectedTab
=
tabIndex
==
config
.
selection
.
previousIndex
;
Color
labelColor
=
isSelectedTab
?
selectedColor
:
color
;
if
(
config
.
selection
.
indexIsChanging
)
{
Color
labelColor
=
color
;
if
(
_selection
!=
null
)
{
final
bool
isSelectedTab
=
tabIndex
==
_selection
.
index
;
final
bool
isPreviouslySelectedTab
=
tabIndex
==
_selection
.
previousIndex
;
labelColor
=
isSelectedTab
?
selectedColor
:
color
;
if
(
_selection
.
indexIsChanging
)
{
if
(
isSelectedTab
)
labelColor
=
Color
.
lerp
(
color
,
selectedColor
,
_
performance
.
progress
);
labelColor
=
Color
.
lerp
(
color
,
selectedColor
,
_selection
.
performance
.
progress
);
else
if
(
isPreviouslySelectedTab
)
labelColor
=
Color
.
lerp
(
selectedColor
,
color
,
_performance
.
progress
);
labelColor
=
Color
.
lerp
(
selectedColor
,
color
,
_selection
.
performance
.
progress
);
}
}
return
new
_Tab
(
onSelected:
()
{
_handleTabSelected
(
tabIndex
);
},
...
...
@@ -610,10 +664,17 @@ class _TabBarState extends ScrollableState<TabBar> {
_viewportSize
=
newSize
;
_updateScrollBehavior
();
if
(
config
.
isScrollable
)
scrollTo
(
_centeredTabScrollOffset
(
config
.
selection
.
index
),
duration:
_kTabBarScroll
);
scrollTo
(
_centeredTabScrollOffset
(
_
selection
.
index
),
duration:
_kTabBarScroll
);
}
Widget
buildContent
(
BuildContext
context
)
{
TabBarSelectionState
oldSelection
=
_selection
;
_selection
=
TabBarSelection
.
of
(
context
);
if
(
oldSelection
!=
_selection
)
{
_removeSelectionListeners
(
oldSelection
);
_addSelectionListeners
(
_selection
);
}
assert
(
config
.
labels
!=
null
&&
config
.
labels
.
isNotEmpty
);
assert
(
Material
.
of
(
context
)
!=
null
);
...
...
@@ -641,7 +702,7 @@ class _TabBarState extends ScrollableState<TabBar> {
style:
textStyle
,
child:
new
_TabBarWrapper
(
children:
tabs
,
selectedIndex:
config
.
selection
.
index
,
selectedIndex:
_selection
?
.
index
,
indicatorColor:
indicatorColor
,
indicatorRect:
_indicatorRect
.
value
,
textAndIcons:
textAndIcons
,
...
...
@@ -669,7 +730,6 @@ class _TabBarState extends ScrollableState<TabBar> {
class
TabBarView
<
T
>
extends
PageableList
<
T
>
{
TabBarView
({
Key
key
,
this
.
selection
,
List
<
T
>
items
,
ItemBuilder
<
T
>
itemBuilder
})
:
super
(
...
...
@@ -681,34 +741,27 @@ class TabBarView<T> extends PageableList<T> {
)
{
assert
(
items
!=
null
);
assert
(
items
.
length
>
1
);
assert
(
selection
!=
null
);
assert
(
selection
.
maxIndex
==
items
.
length
-
1
);
}
final
TabBarSelection
selection
;
_TabBarViewState
createState
()
=>
new
_TabBarViewState
<
T
>();
}
class
_TabBarViewState
<
T
>
extends
PageableListState
<
T
,
TabBarView
<
T
>>
{
TabBarSelectionState
_selection
;
List
<
int
>
_itemIndices
=
[
0
,
1
];
AnimationDirection
_scrollDirection
=
AnimationDirection
.
forward
;
int
get
_tabCount
=>
config
.
items
.
length
;
void
_initItemIndicesAndScrollPosition
()
{
final
int
selectedIndex
=
config
.
selection
.
index
;
if
(
selectedIndex
==
0
)
{
_itemIndices
=
<
int
>[
0
,
1
];
scrollTo
(
0.0
);
}
else
if
(
selectedIndex
==
_tabCount
-
1
)
{
_itemIndices
=
<
int
>[
selectedIndex
-
1
,
selectedIndex
];
scrollTo
(
1.0
);
}
else
{
_itemIndices
=
<
int
>[
selectedIndex
-
1
,
selectedIndex
,
selectedIndex
+
1
];
scrollTo
(
1.0
);
void
_addSelectionListeners
(
TabBarSelectionState
selection
)
{
if
(
selection
!=
null
)
selection
.
_performance
.
addListener
(
_handleProgressChange
);
}
void
_removeSelectionListeners
(
TabBarSelectionState
selection
)
{
if
(
selection
!=
null
)
selection
.
_performance
.
removeListener
(
_handleProgressChange
);
}
BoundedBehavior
_boundedBehavior
;
...
...
@@ -718,37 +771,43 @@ class _TabBarViewState<T> extends PageableListState<T, TabBarView<T>> {
return
_boundedBehavior
;
}
Performance
get
_performance
=>
config
.
selection
.
_performance
;
void
initState
()
{
super
.
initState
();
_initItemIndicesAndScrollPosition
();
_performance
..
addListener
(
_handleProgressChange
);
}
void
dispose
()
{
_performance
..
removeListener
(
_handleProgressChange
)
..
stop
();
_removeSelectionListeners
(
_selection
);
super
.
dispose
();
}
void
_initItemIndicesAndScrollPosition
()
{
assert
(
_selection
!=
null
);
final
int
selectedIndex
=
_selection
.
index
;
if
(
selectedIndex
==
0
)
{
_itemIndices
=
<
int
>[
0
,
1
];
scrollTo
(
0.0
);
}
else
if
(
selectedIndex
==
_tabCount
-
1
)
{
_itemIndices
=
<
int
>[
selectedIndex
-
1
,
selectedIndex
];
scrollTo
(
1.0
);
}
else
{
_itemIndices
=
<
int
>[
selectedIndex
-
1
,
selectedIndex
,
selectedIndex
+
1
];
scrollTo
(
1.0
);
}
}
void
_handleProgressChange
()
{
if
(
!
config
.
selection
.
indexIsChanging
)
if
(
_selection
==
null
||
!
_
selection
.
indexIsChanging
)
return
;
// The TabBar is driving the TabBarSelection performance.
if
(
_performance
.
status
==
PerformanceStatus
.
completed
)
{
final
Performance
performance
=
_selection
.
performance
;
if
(
performance
.
status
==
PerformanceStatus
.
completed
)
{
_initItemIndicesAndScrollPosition
();
return
;
}
if
(
_
performance
.
status
!=
PerformanceStatus
.
forward
)
if
(
performance
.
status
!=
PerformanceStatus
.
forward
)
return
;
final
int
selectedIndex
=
config
.
selection
.
index
;
final
int
previousSelectedIndex
=
config
.
selection
.
previousIndex
;
final
int
selectedIndex
=
_
selection
.
index
;
final
int
previousSelectedIndex
=
_
selection
.
previousIndex
;
if
(
selectedIndex
<
previousSelectedIndex
)
{
_itemIndices
=
<
int
>[
selectedIndex
,
previousSelectedIndex
];
...
...
@@ -759,53 +818,63 @@ class _TabBarViewState<T> extends PageableListState<T, TabBarView<T>> {
}
if
(
_scrollDirection
==
AnimationDirection
.
forward
)
scrollTo
(
_
performance
.
progress
);
scrollTo
(
performance
.
progress
);
else
scrollTo
(
1.0
-
_
performance
.
progress
);
scrollTo
(
1.0
-
performance
.
progress
);
}
int
get
itemCount
=>
_itemIndices
.
length
;
List
<
Widget
>
buildItems
(
BuildContext
context
,
int
start
,
int
count
)
{
return
_itemIndices
.
skip
(
start
)
.
take
(
count
)
.
map
((
int
i
)
=>
config
.
itemBuilder
(
context
,
config
.
items
[
i
],
i
))
.
toList
();
}
void
dispatchOnScroll
()
{
if
(
config
.
selection
.
indexIsChanging
)
if
(
_selection
==
null
||
_
selection
.
indexIsChanging
)
return
;
// This class is driving the TabBarSelection's performance.
if
(
config
.
selection
.
index
==
0
||
config
.
selection
.
index
==
_tabCount
-
1
)
_performance
.
progress
=
scrollOffset
;
final
Performance
performance
=
_selection
.
_performance
;
if
(
_selection
.
index
==
0
||
_selection
.
index
==
_tabCount
-
1
)
performance
.
progress
=
scrollOffset
;
else
_
performance
.
progress
=
scrollOffset
/
2.0
;
performance
.
progress
=
scrollOffset
/
2.0
;
}
Future
fling
(
Offset
scrollVelocity
)
{
// TODO(hansmuller): should not short-circuit in this case.
if
(
config
.
selection
.
indexIsChanging
)
if
(
_selection
==
null
||
_
selection
.
indexIsChanging
)
return
new
Future
.
value
();
if
(
scrollVelocity
.
dx
.
abs
()
>
_kMinFlingVelocity
)
{
final
int
selectionDelta
=
scrollVelocity
.
dx
>
0
?
-
1
:
1
;
config
.
selection
.
index
=
(
config
.
selection
.
index
+
selectionDelta
).
clamp
(
0
,
_tabCount
-
1
);
_selection
.
index
=
(
_
selection
.
index
+
selectionDelta
).
clamp
(
0
,
_tabCount
-
1
);
return
new
Future
.
value
();
}
final
int
selectionIndex
=
config
.
selection
.
index
;
final
int
selectionIndex
=
_
selection
.
index
;
final
int
settleIndex
=
snapScrollOffset
(
scrollOffset
).
toInt
();
if
(
selectionIndex
>
0
&&
settleIndex
!=
1
)
{
config
.
selection
.
index
+=
settleIndex
==
2
?
1
:
-
1
;
_
selection
.
index
+=
settleIndex
==
2
?
1
:
-
1
;
return
new
Future
.
value
();
}
else
if
(
selectionIndex
==
0
&&
settleIndex
==
1
)
{
config
.
selection
.
index
=
1
;
_
selection
.
index
=
1
;
return
new
Future
.
value
();
}
return
settleScrollOffset
();
}
List
<
Widget
>
buildItems
(
BuildContext
context
,
int
start
,
int
count
)
{
TabBarSelectionState
oldSelection
=
_selection
;
_selection
=
TabBarSelection
.
of
(
context
);
if
(
oldSelection
!=
_selection
)
{
_removeSelectionListeners
(
oldSelection
);
_addSelectionListeners
(
_selection
);
if
(
_selection
!=
null
)
_initItemIndicesAndScrollPosition
();
}
return
_itemIndices
.
skip
(
start
)
.
take
(
count
)
.
map
((
int
i
)
=>
config
.
itemBuilder
(
context
,
config
.
items
[
i
],
i
))
.
toList
();
}
}
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