简体   繁体   English

Flutter 带标签栏和网格视图的银色应用栏

[英]Flutter sliver app bar with tab bar and grid view

I want to use sliver app bar with tab bar and grid view.我想使用带有标签栏和网格视图的条子应用栏。
I tried this code:我试过这段代码:

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxScrolled) {
            return <Widget>[
              SliverAppBar(
                backgroundColor: Colors.white,
                centerTitle: true,
                pinned: true,
                snap: false,
                floating: true,
                title: Image(
                  image: AssetImage('assets/images/appbar_logo.png'),
                  width: 152,
                  height: 42,
                ),
                bottom: PreferredSize(
                  preferredSize: Size.fromHeight(48),
                  child: TabBar(
                    isScrollable: true,
                    automaticIndicatorColorAdjustment: false,
                    indicatorSize: TabBarIndicatorSize.tab,
                    tabs: STR_TAB_TITLE_LIST.map((e) => Container(
                        padding: EdgeInsets.only(left: 4, right: 4),
                        child: Tab(text: e),
                      ),
                    ).toList(),
                    controller: _tabController,
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            children: []..addAll(STR_TAB_TITLE_LIST.map((e) {
              if (e == 'myWork') {
                return MyWorkPage(e);
              } else if (e == 'character') {
                return CharactersPage(onCharacterPageItemSelected, e);
              }
              return TabPage(e);
            })),
            controller: _tabController,
          ),
        ),
      ),
    );
  }

And pages:和页面:

@override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topCenter,
      child: GridView.builder(
        shrinkWrap: true,
        padding: EdgeInsets.all(4.0),
        physics: BouncingScrollPhysics(),
        itemCount: SAMPLE_CARD_LIST.length,
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2,
        ),
        itemBuilder: (context, index) {
          return ItemCard(SAMPLE_CARD_LIST[index]);
        },
      ),
    );
  }

The problems I faced are two我遇到的问题有两个

  1. It does not save page's scroll position它不保存页面的滚动 position
    like this: https://github.com/flutter/flutter/issues/40740像这样: https://github.com/flutter/flutter/issues/40740
  2. it cuts top of page when swipe to next tab滑动到下一个标签时它会切到页面顶部
    like this: Flutter TabBar and SliverAppBar that hides when you scroll down像这样: Flutter 向下滚动时隐藏的 TabBar 和 SliverAppBar

I tried all suggestions above links but it did not worked我尝试了以上链接的所有建议,但没有奏效
How can I fix this?我怎样才能解决这个问题?

Use of code: You can make your custom appbar.代码的使用:您可以制作自定义应用程序栏。 I think this code will help you.我认为这段代码会对你有所帮助。

      appBar: CustomTab(
        onDone: (tabNo) {
          
        },
      ),)

Where we have used:我们用过的地方:


import 'package:filepath/md2indicator.dart';


class CustomTab extends StatefulWidget implements PreferredSizeWidget {
  final void Function(int) onDone;

  CustomTab({
    Key? key,
    required this.onDone,
  }) : super(key: key);

  @override
  State<CustomTab> createState() => _CustomTabState();

  @override
  // TODO: implement preferredSize
  final Size preferredSize = const Size.fromHeight(kToolbarHeight);
}

class _CustomTabState extends State<CustomTab>
    with SingleTickerProviderStateMixin {
  late TabController tabcontroller;

  // final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    tabcontroller = TabController(length: 9, vsync: this);
    tabcontroller.addListener(() {
      setState(() {
        widget.onDone(tabcontroller.index);
        tabcontroller.animateTo(tabcontroller.index);
      });
    });
  }

  @override
  void dispose() {
    tabcontroller.dispose();
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: TabBar(
        controller: tabcontroller,
        labelStyle: TextStyle(
          fontWeight: FontWeight.w700,
        ),
        indicatorSize: TabBarIndicatorSize.label,
        labelColor: Colors.green,
        unselectedLabelColor: Colors.black,
        isScrollable: true,
        indicator: MD2Indicator(
          indicatorHeight: 3,
          indicatorColor: Colors.green.shade700,
          indicatorSize: MD2IndicatorSize.full,
        ),
        tabs: [
          Tab(
            text: 'Trending',
          ),
          Tab(
            text: 'Sports',
          ),
          Tab(
            text: 'Economy',
          ),
          Tab(
            text: 'Fashion',
          ),
          Tab(
            text: 'Entertainment',
          ),
          Tab(
            text: 'Technology',
          ),
          Tab(
            text: 'POLITICS',
          ),
          Tab(
            text: 'Viral',
          ),
          Tab(
            text: 'Videos',
          )
        ],
      ),
    );
  }
}

And custom tab bar md2_tab_indicator style can be designed as:而自定义tab bar md2_tab_indicator样式可以设计为:


import 'package:flutter/widgets.dart';

enum MD2IndicatorSize {
  tiny,
  normal,
  full,
}

class MD2Indicator extends Decoration {
  final double indicatorHeight;
  final Color indicatorColor;
  final MD2IndicatorSize indicatorSize;

  const MD2Indicator({
    required this.indicatorHeight,
    required this.indicatorColor,
    required this.indicatorSize,
  });

  @override
  _MD2Painter createBoxPainter([VoidCallback? onChanged]) {
    return _MD2Painter(this, onChanged);
  }
}

class _MD2Painter extends BoxPainter {
  final MD2Indicator decoration;

  _MD2Painter(this.decoration, VoidCallback? onChanged) : super(onChanged);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration.size != null);

    Rect rect;
    if (decoration.indicatorSize == MD2IndicatorSize.full) {
      rect = Offset(
            offset.dx,
            configuration.size!.height - decoration.indicatorHeight,
          ) &
          Size(configuration.size!.width, decoration.indicatorHeight);
    } else if (decoration.indicatorSize == MD2IndicatorSize.tiny) {
      rect = Offset(
            offset.dx + configuration.size!.width / 2 - 8,
            configuration.size!.height - decoration.indicatorHeight,
          ) &
          Size(16, decoration.indicatorHeight);
    } else {
      rect = Offset(
            offset.dx + 6,
            configuration.size!.height - decoration.indicatorHeight,
          ) &
          Size(configuration.size!.width - 12, decoration.indicatorHeight);
    }

    final Paint paint = Paint()
      ..color = decoration.indicatorColor
      ..style = PaintingStyle.fill;

    canvas.drawRRect(
      RRect.fromRectAndCorners(
        rect,
        topRight: Radius.circular(8),
        topLeft: Radius.circular(8),
      ),
      paint,
    );
  }
}```

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM