1、自动适应宽度未做,文本都没有难度,但下面的指示器的移动要获取text的宽度有点麻烦,所以就偷懒个懒,暂时没有做;
2、标题用的row,不能满足多个(超出屏幕宽度)title的情况,可以换成ListView,请问指示器 移动的问题,怎么处理呢?
如果您有好的方法,欢迎推荐
源码
import 'package:flutter/material.dart';
class SpecialSubTitleWidget extends StatefulWidget {
final List<String> titleList;
//正常item的点击回调
final Function(dynamic) titleClickActionBlock;
const SpecialSubTitleWidget({
Key? key,
required this.titleList,
required this.titleClickActionBlock,
// this.rowNumber = 4,
// this.maxShowItemNumber = 0,
// this.itemAspectRatio = 1.0,
// this.mainAxisSpacing = 10.0,
// this.crossAxisSpacing = 10.0,
// this.itemTextFontSize = 14.0,
// this.showMoreButton = false,
// this.isCanScrollable = true,
// this.moreButtonClickActionBlock,
// this.backgroundColor,
// this.itemBackgroundColor,
}) : super(key: key);
@override
State<SpecialSubTitleWidget> createState() => _SpecialSubTitleWidgetState();
}
class _SpecialSubTitleWidgetState extends State<SpecialSubTitleWidget> {
late List<SpecialTextButton> titleBtnList;
late List<bool> buttonStates;
int currentSelectIndex = 0;
double indicatorLeft = 0;
double itemW = 45;
@override
void initState() {
titleBtnList = [];
super.initState();
}
@override
Widget build(BuildContext context) {
return pageItemBar();
}
Widget pageItemBar() {
return Container(
height: 50,
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(child: Row(children: creatTitleButtons(widget.titleList))),
SizedBox(
height: 3,
width: double.infinity,
child: Stack(
children: [
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
height: 1,
color: Colors.red,
),
),
Positioned(
left: indicatorLeft,
child: Container(
height: 3,
width: itemW,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
topRight: Radius.circular(4))))),
],
),
)
],
),
);
}
//方法
creatTitleButtons(List titles) {
if (titles.isEmpty) {
return;
}
//默认所以按钮不选中
buttonStates = List.generate(titles.length, (index) => false);
//默认选中第一个
buttonStates[currentSelectIndex] = true;
titleBtnList = titles.map((e) {
int index = titles.indexOf(e);
return SpecialTextButton(
titleStr: e,
selected: buttonStates[index],
index: index,
onPressed: (newIndex) {
widget.titleClickActionBlock(newIndex);
setState(() {
buttonStates[currentSelectIndex] = false;
buttonStates[newIndex] = true;
currentSelectIndex = newIndex;
indicatorLeft = newIndex * itemW;
});
});
}).toList();
return titleBtnList;
}
}
class SpecialTextButton extends StatefulWidget {
final String titleStr;
final Function(int) onPressed;
final bool selected;
final int index;
final double fontSizeSele;
final double fontSizeNormal;
final Color colorSele;
final Color colorNormal;
//正常item的点击回调
const SpecialTextButton({
Key? key,
required this.titleStr,
required this.onPressed,
required this.selected,
required this.index,
this.fontSizeSele = 18,
this.fontSizeNormal = 16,
this.colorNormal = Colors.black,
this.colorSele = Colors.blue,
}) : super(key: key);
@override
State<SpecialTextButton> createState() => _SpecialTextButtonState();
}
class _SpecialTextButtonState extends State<SpecialTextButton> {
late TextStyle normalStyle;
late TextStyle selectStyle;
@override
void initState() {
super.initState();
normalStyle =
TextStyle(fontSize: widget.fontSizeNormal, color: widget.colorNormal);//,decoration: TextDecoration.none
selectStyle =
TextStyle(fontSize: widget.fontSizeSele, color: widget.colorSele);//,decoration: TextDecoration.none
}
@override
Widget build(BuildContext context) {
return Material(child: GestureDetector(
onTap: () => widget.onPressed(widget.index),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Text(widget.titleStr,
style: widget.selected ? selectStyle : normalStyle))));
}
}
使用方法
child: SpecialSubTitleWidget(titleList: const ["应用","本地","按钮3"], titleClickActionBlock: (index){
print("------------click: $index --------");
}),