赞
踩
CustomScrollView、SliverList
一、滚动条嵌套
现实场景中可能会出现嵌套布局的情况,其实这种场景和吸顶基本是一致,可以采用同样是方法实现上述两种场景。
首先我们可以看下嵌套的效果。
整个页面是一个滚动,白色部分其实是内嵌的滚动。当然我这样看可能和一般的滚动没什么区别。为了更直观的表现嵌套,可以加上吸顶的效果,这样就可以直观的看到嵌套的效果了。
-
- import 'dart:math';
- import 'package:flutter/material.dart';
- import './../../component/menu.tab.dart';
-
- class Surprise extends StatefulWidget {
- const Surprise({Key? key}) : super(key: key);
- static const routeName = '/test3';
- @override
- State<Surprise> createState() => _SurpriseState();
- }
-
- class _SurpriseState extends State<Surprise> {
-
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- toolbarHeight: 0,
- backgroundColor: Colors.white,
- elevation: 0,
- ),
- backgroundColor:const Color(0xFFfafafa),
- body:CustomScrollView(
- slivers: <Widget>[
- _buildBanner(),
- _buildStickyBar(),
- _buildList(),
- ],
- )
- );
- }
-
- Widget _buildBanner() {
- return SliverToBoxAdapter(
- child:SizedBox(
- height: 200,
- child:Stack(
- children: [
- SizedBox(
- width: double.infinity,
- height: 200,
- child: Image.network(
- "https://img30.360buyimg.com/img/jfs/t1/92581/29/20454/374562/61de544fE1d5e1e34/f69d41d732f3fe81.jpg",
- height: double.infinity,
- fit: BoxFit.fill,
- ),
- ),
- Positioned(
- bottom: -1,
- width: MediaQuery.of(context).size.width,
- child: Container(
- height: 10,
- decoration:const BoxDecoration(
- color:Color(0xFFfafafa),
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(6),
- topRight: Radius.circular(6),
- )
- ),
- )
- )
- ],
- ),
- )
- );
- }
-
- Widget _buildStickyBar() {
- return SliverPersistentHeader(
- pinned: true, //是否固定在顶部
- floating: true,
- delegate: _SliverAppBarDelegate(
- minHeight: 50, //收起的高度
- maxHeight: 50, //展开的最大高度
- child: Container(
- padding: const EdgeInsets.only(left: 16),
- color:const Color(0xFFfafafa),
- alignment: Alignment.centerLeft,
- child: Row(
- children: [
- Container(
- width: 50,
- alignment: Alignment.center,
- child: const Text("精选", style: TextStyle(fontSize: 18)),
- ),
- Expanded(
- child:MenuTab(
- menuList:const [
- {"value":"1","text":"京喜自营"},
- {"value":"2","text":"母婴玩具"},
- {"value":"3","text":"生活百货"},
- {"value":"4","text":"酒水饮料"},
- {"value":"5","text":"家清纸品"},
- {"value":"6","text":"米面粮油"},
- {"value":"7","text":"数码配件"},
- {"value":"8","text":"大小家电"},
- {"value":"9","text":"服饰鞋靴"},
- {"value":"10","text":"美妆个护"},
- {"value":"11","text":"休闲零食"},
- ],
- onPress: (e){
- setState(() {
- });
- },
- )
- )
- ],
- ),
- )),
- );
- }
-
- Widget _buildList() {
- return SliverList(
- delegate: SliverChildBuilderDelegate(
- (context, index) {
-
- return Container(
- height: 100,
- alignment: Alignment.center,
- child: Text("$index,Container"),
- );
- },
- childCount:10,
- ));
- }
- }
-
- class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
- _SliverAppBarDelegate({
- required this.minHeight,
- required this.maxHeight,
- required this.child,
- });
-
- final double minHeight;
- final double maxHeight;
- final Widget child;
-
- @override
- double get minExtent => minHeight;
-
- @override
- double get maxExtent => max(maxHeight, minHeight);
-
- @override
- Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
- return SizedBox.expand(child: child);
- }
-
- @override
- bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
- return maxHeight != oldDelegate.maxHeight ||
- minHeight != oldDelegate.minHeight ||
- child != oldDelegate.child;
- }
- }
-
-
- import 'package:flutter/material.dart';
- class MenuTab extends StatefulWidget {
- final Function? onPress;
- final List<Map<String, dynamic>> menuList;
- const MenuTab({Key? key,required this.menuList,this.onPress}) : super(key: key);
-
- @override
- State<MenuTab> createState() => _MenuTabState();
- }
-
- class _MenuTabState extends State<MenuTab> {
- final ScrollController _controller = ScrollController();
- late String currerValue = "";
- final GlobalKey menuTabListKey = GlobalKey();
-
- List<Widget> generateMenuTabList (){
- List<Widget> menuTabList = [];
- for(var i = 0; i < widget.menuList.length; i++){
- menuTabList.add(
- InkResponse(
- splashColor:Colors.transparent,
- splashFactory: NoSplash.splashFactory,
- child:Container(
- width: 100,
- alignment: Alignment.center,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(
- widget.menuList[i]["text"],
- style: TextStyle(
- fontWeight: currerValue== widget.menuList[i]["value"] as String?FontWeight.bold:FontWeight.normal,
- fontSize: currerValue== widget.menuList[i]["value"] as String?20:18,
- color: currerValue== widget.menuList[i]["value"] as String? const Color(0xFFf81818):const Color(0xFF000000)
- )
- ),
- SizedBox(
- width: 50,
- height: 2,
- child: DecoratedBox(
- decoration: BoxDecoration(
- color: currerValue== widget.menuList[i]["value"] as String?const Color(0xFFf81818):Colors.transparent
- ),
- )
- )
- ],
- )
- ),
- onTap: (){
- chosenTab(widget.menuList[i],i);
- if(widget.onPress!=null){
- widget.onPress!(widget.menuList[i]);
- }
- },
- ),
- );
- }
- return menuTabList;
- }
-
-
- void chosenTab(item,int index){
- double containerWidth =menuTabListKey.currentContext!.size!.width;
- if(containerWidth/2<((index+1)*100-50)){
- _controller.animateTo((index+1)*100-containerWidth/2,duration: const Duration(seconds: 1), curve: Curves.ease);
- }else{
- _controller.animateTo(0,duration: const Duration(seconds: 1), curve: Curves.ease);
- }
- setState(() {
- currerValue =item['value'] as String;
- });
- }
- @override
- Widget build(BuildContext context) {
- return ListView(
- key: menuTabListKey,
- scrollDirection: Axis.horizontal,
- controller: _controller,
- children: generateMenuTabList(),
- );
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。