You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
6.6 KiB
208 lines
6.6 KiB
import 'package:flutter/material.dart'; |
|
import 'package:flutter/rendering.dart'; |
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
import 'package:huixiang/retrofit/data/brand.dart'; |
|
import 'package:huixiang/view_widget/icon_text.dart'; |
|
|
|
class StoreTitleTab extends StatefulWidget { |
|
final ScrollController scrollController; |
|
final List<Brand> brands; |
|
|
|
final List<GlobalKey> globaKeys; |
|
final bool isScroll; |
|
|
|
StoreTitleTab( |
|
this.brands, |
|
this.globaKeys, |
|
this.scrollController, { |
|
this.isScroll = false, |
|
}); |
|
|
|
@override |
|
State<StatefulWidget> createState() { |
|
return _StoreTitleTab(); |
|
} |
|
} |
|
|
|
class _StoreTitleTab extends State<StoreTitleTab> { |
|
int selectedIndex = -1; |
|
int selectedIndex1 = -1; |
|
bool isVisible = false; |
|
|
|
List<GlobalKey> _globalKeys = []; |
|
|
|
@override |
|
void initState() { |
|
super.initState(); |
|
|
|
if (widget.brands != null) { |
|
widget.brands.forEach((element) { |
|
_globalKeys.add(GlobalKey()); |
|
}); |
|
} |
|
|
|
if (widget.scrollController != null && |
|
widget.globaKeys != null && |
|
widget.globaKeys.length > 0) { |
|
widget.scrollController?.addListener(() { |
|
if (widget.globaKeys[0].currentContext == null) return; |
|
RenderBox firstRenderBox = |
|
widget.globaKeys[0].currentContext.findRenderObject(); |
|
Offset first = firstRenderBox?.localToGlobal(Offset.zero); |
|
|
|
var top = 96.h; |
|
if (first.dy <= top) { |
|
if (!isVisible) { |
|
isVisible = true; |
|
setState(() {}); |
|
} |
|
} else { |
|
var b = isVisible; |
|
isVisible = false; |
|
if (b) setState(() {}); |
|
selectedIndex = -1; |
|
} |
|
|
|
widget.globaKeys.forEach((element) { |
|
if (widget.globaKeys.indexOf(element) < |
|
(widget.globaKeys.length - 1)) { |
|
if (element.currentContext == null) return; |
|
RenderBox renderBox = element.currentContext.findRenderObject(); |
|
Offset offset = renderBox?.localToGlobal(Offset.zero); |
|
int nextIndex = widget.globaKeys.indexOf(element) + 1; |
|
RenderBox nextRenderBox = |
|
widget.globaKeys[nextIndex].currentContext.findRenderObject(); |
|
Offset nextOffset = nextRenderBox?.localToGlobal(Offset.zero); |
|
|
|
if (offset.dy <= top && nextOffset.dy > top) { |
|
selectedIndex = widget.globaKeys.indexOf(element); |
|
if (selectedIndex1 != selectedIndex) { |
|
setState(() { |
|
print("object:$selectedIndex"); |
|
if (!isClickScroll) { |
|
scrollTab(selectedIndex); |
|
} else if (selectedIndex == clickIndex) { |
|
isClickScroll = false; |
|
clickIndex = -1; |
|
} |
|
}); |
|
selectedIndex1 = selectedIndex; |
|
} |
|
return; |
|
} |
|
} else { |
|
RenderBox lastRenderBox = element.currentContext.findRenderObject(); |
|
Offset lastOffset = lastRenderBox?.localToGlobal(Offset.zero); |
|
if (lastOffset.dy <= top) { |
|
selectedIndex = widget.globaKeys.indexOf(element); |
|
if (selectedIndex1 != selectedIndex) { |
|
setState(() { |
|
print("object:$selectedIndex"); |
|
if (!isClickScroll) { |
|
scrollTab(selectedIndex); |
|
} else if (selectedIndex == clickIndex) { |
|
isClickScroll = false; |
|
clickIndex = -1; |
|
} |
|
}); |
|
selectedIndex1 = selectedIndex; |
|
} |
|
return; |
|
} |
|
} |
|
}); |
|
}); |
|
} |
|
} |
|
|
|
scrollTab(index) { |
|
if (_globalKeys[index].currentContext == null) return; |
|
RenderBox renderBox = _globalKeys[index].currentContext.findRenderObject(); |
|
Offset nextOffset = renderBox?.localToGlobal(Offset.zero); |
|
double widgetWidth = renderBox.size.width; |
|
double screenWidth = MediaQuery.of(context).size.width; |
|
if (nextOffset.dx < 0 || (nextOffset.dx + widgetWidth) > screenWidth) { |
|
scrollController.animateTo( |
|
nextOffset.dx/* < 0 ? nextOffset.dx : (nextOffset.dx + widgetWidth)*/, |
|
duration: Duration(seconds: 1), curve: Curves.ease, |
|
); |
|
} |
|
} |
|
|
|
ScrollController scrollController = ScrollController(); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Visibility( |
|
visible: (!widget.isScroll) ? true : isVisible, |
|
child: SingleChildScrollView( |
|
scrollDirection: Axis.horizontal, |
|
controller: scrollController, |
|
physics: BouncingScrollPhysics(), |
|
child: Container( |
|
height: 52.h, |
|
constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width), |
|
color: Colors.white, |
|
alignment: Alignment.center, |
|
child: Row( |
|
mainAxisAlignment: MainAxisAlignment.spaceAround, |
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
children: (widget.brands == null || widget.brands.length == 0) |
|
? [] |
|
: (widget.brands.map((e) { |
|
return item(e, selectedIndex == widget.brands.indexOf(e), |
|
widget.brands.indexOf(e)); |
|
}).toList()), |
|
), |
|
), |
|
), |
|
); |
|
} |
|
|
|
bool isClickScroll = false; |
|
int clickIndex = -1; |
|
|
|
Widget item(Brand text, isSelected, index) { |
|
return GestureDetector( |
|
onTap: () { |
|
FlexParentData parentData = widget.globaKeys[index].currentContext.findRenderObject().parentData; |
|
double offset = parentData.offset.dy - 52.h + 20.h; |
|
isClickScroll = true; |
|
clickIndex = index; |
|
widget.scrollController.animateTo(offset, duration: Duration(seconds: 1), curve: Curves.ease); |
|
}, |
|
child: Container( |
|
key: _globalKeys.length > 0 ? _globalKeys[index] : GlobalKey(), |
|
padding: EdgeInsets.symmetric(horizontal: 15.w), |
|
child: tabItem(text, isSelected), |
|
), |
|
); |
|
} |
|
|
|
Widget tabItem(Brand text, isSelected) { |
|
if (isSelected) { |
|
return IconText( |
|
text.name, |
|
isMax: false, |
|
rightImage: text.icon ?? "assets/image/icon_xuanzhong.webp", |
|
iconSize: 16, |
|
iconColor: Colors.red, |
|
textStyle: TextStyle( |
|
fontWeight: FontWeight.bold, |
|
fontSize: 16.sp, |
|
color: Color(0xFF353535), |
|
), |
|
); |
|
} else { |
|
return IconText( |
|
text.name, |
|
isMax: false, |
|
textStyle: TextStyle( |
|
fontWeight: FontWeight.bold, |
|
fontSize: 16.sp, |
|
color: Color(0xFF353535), |
|
), |
|
); |
|
} |
|
} |
|
}
|
|
|