在flutter中TabBar + TabBarView可以實(shí)現(xiàn)類似Android中的indicator + viewpage的效果.
一.TabBar參數(shù)
參數(shù) | 說明 |
---|---|
unselectedLabelColor | 未選中時(shí)標(biāo)簽的顏色 |
labelColor | 選中時(shí)標(biāo)簽的顏色 |
indicatorColor | 指示器顏色 |
indicatorWeight | 指示器高度 |
indicatorSize | 指示器寬度, 值為tab或lable |
indicator | 指示器的形狀, 類型為Decoration |
一般可以為indicator
設(shè)置UnderlineTabIndicator
對象. 而indicatorColor
和indicatorWeight
內(nèi)部其實(shí)也是構(gòu)建了 UnderlineTabIndicator
.
具體源碼為:(tabs.dart/_TabBarState)
Decoration get _indicator {
if (widget.indicator != null)
return widget.indicator;
final ThemeData themeData = Theme.of(context);
if (themeData.tabBarTheme.indicator != null)
return themeData.tabBarTheme.indicator;
Color color = widget.indicatorColor ?? themeData.indicatorColor;
if (color.value == Material.of(context).color.value)
color = Colors.white;
return UnderlineTabIndicator(
insets: widget.indicatorPadding,
borderSide: BorderSide(
width: widget.indicatorWeight,
color: color,
),
);
}
而indicatorSize
則傳遞給了_IndicatorPainter
. 其根據(jù)tab
orlabel
計(jì)算繪制區(qū)域大小.
Rect indicatorRect(Size tabBarSize, int tabIndex) {
assert(_currentTabOffsets != null);
assert(_currentTextDirection != null);
assert(_currentTabOffsets.isNotEmpty);
assert(tabIndex >= 0);
assert(tabIndex <= maxTabIndex);
double tabLeft, tabRight;
switch (_currentTextDirection) {
case TextDirection.rtl:
tabLeft = _currentTabOffsets[tabIndex + 1];
tabRight = _currentTabOffsets[tabIndex];
break;
case TextDirection.ltr:
tabLeft = _currentTabOffsets[tabIndex];
tabRight = _currentTabOffsets[tabIndex + 1];
break;
}
if (indicatorSize == TabBarIndicatorSize.label) {
final double tabWidth = tabKeys[tabIndex].currentContext.size.width;
final double delta = ((tabRight - tabLeft) - tabWidth) / 2.0;
tabLeft += delta;
tabRight -= delta;
}
return Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height);
}
二. 自定義indicator
比如我們想支持指定寬度, 上面的那些參數(shù)無法達(dá)成, 那就需要重寫一個(gè)自定義Decoration. 直接copyUnderlineTabIndicator
代碼
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
return Rect.fromLTWH(
indicator.left,
indicator.bottom - borderSide.width,
indicator.width,
borderSide.width,
);
}
修改為
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
//希望的寬度
double wantWidth = 20;
//取中間坐標(biāo)
double cw = (indicator.left + indicator.right) / 2;
return Rect.fromLTWH(cw - wantWidth / 2,
indicator.bottom - borderSide.width, wantWidth, borderSide.width);
}