gpt4 book ai didi

flutter - 带有 StickyHeader 的 Sliver 内部的 TabBarView

转载 作者:行者123 更新时间:2023-12-01 23:17:31 26 4
gpt4 key购买 nike

到目前为止,我已经使用 CustomScrollView 和 Sticky Header 制作了这个布局

https://imgur.com/a/Xo4AfAM

我想要实现的是,选项卡下方的内容不应滚动,除非有额外的内容可用。此外,滚动后,内容不应位于粘性标题后面。

到目前为止我的代码。

Scaffold(
backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
appBar: AppBar(
toolbarHeight: getHeight() * (1 / 11),
),
body: Padding(
padding: getPaddings(),
child: DefaultTabController(
length: 3,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: getHeight() * (3 / 11),
color: Colors.blue,
),
),
SliverStickyHeader(
header: Column(
children: [
Container(
height: getHeight() * (1 / 11),
width: double.infinity,
color: kPrimaryColor,
child: Center(
child: Text(
"TEXT",
style: TextStyle(
fontSize: 32,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
Container(
height: getHeight() * (1 / 11),
color: kPrimaryColor,
child: TabBar(
tabs: [
Tab(
child: Text(
'TITLE1',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE2',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE3',
style: TextStyle(color: Colors.black),
),
),
],
),
),
],
),
sliver: SliverFillRemaining(
child: TabBarView(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(50),
vertical: getProportionateScreenHeight(20)),
child: Column(
children: [
RoundedPicture(),
FittedBox(
child: Text("Hello World",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 40)),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info1: ',
children: [
TextSpan(
text: "123",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info2: ',
children: [
TextSpan(
text: "abcd",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info3: ',
children: [
TextSpan(
text: "xyz",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
],
),
],
),
),
Center(
child: Text("TITLE2"),
),
Center(
child: Text("TITLE3"),
),
],
),
),
),
],
),
),
),

为了实现所需的布局,我尝试在不同的条子内使用 TabBarView,即 SliverList 和 SliverToBoxAdapter,但它们都导致了错误,因为 TabBarView 没有预定义的高度。

最佳答案

这是我的实现。
因为没有size相关的方法,所以我自己定了一个值。

  • 堆栈
    • 默认选项卡 Controller

      • 嵌套 ScrollView
        • SliverAppBar

        • SliverPersistentHeader

        • SliverPersistentHeader

        • 标签栏 View

    • 容器//后退按钮

enter image description here

import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(initialIndex: 0, length: 3, vsync: this);
}

double getHeight() {
return 800;
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(
children: [
DefaultTabController(
length: 3,
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverAppBar(
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: getHeight() * (1 / 11),
width: double.infinity,
color: Colors.green[200],
child: Center(
child: Text(
"TEXT",
style: TextStyle(
fontSize: 32,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
color: Colors.green[200],
child: TabBar(
controller: _tabController,
tabs: [
Tab(
child: Text(
'TITLE1',
style: TextStyle(
color: Colors.black,
),
),
),
Tab(
child: Text(
'TITLE2',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE3',
style: TextStyle(color: Colors.black),
),
),
],
),
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
// RoundedPicture(),
Icon(
Icons.favorite,
color: Colors.pink,
size: 150.0,
semanticLabel:
'Text to announce in accessibility modes',
),
FittedBox(
child: Text("Hello World",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 40)),
),
SizedBox(
height: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info1: ',
children: [
TextSpan(
text: "123",
style: TextStyle(),
),
]),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info2: ',
children: [
TextSpan(
text: "abcd",
style: TextStyle(),
),
]),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info3: ',
children: [
TextSpan(
text: "xyz",
style: TextStyle(),
),
]),
),
],
),
],
),
),
),
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
Container(
padding: EdgeInsets.only(bottom: 600),
child: Center(
child: Text("TITLE2"),
),
),
],
),
),
),
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
Container(
padding: EdgeInsets.only(bottom: 600),
child: Center(
child: Text("TITLE3"),
),
),
],
),
),
),
],
),
),
),
Container(
height: 90,
padding: EdgeInsets.symmetric(horizontal: 15),
child: InkWell(
onTap: () {},
child: Icon(Icons.arrow_back),
),
),
],
),
),
);
}
}

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 => math.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;
}
}

关于flutter - 带有 StickyHeader 的 Sliver 内部的 TabBarView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68640078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com