--- РЕДАКТИРОВАТЬ 1 -
Хорошо, поэтому я собрал кое-что быстрое для вас.Я следил за этой статьей (написанной Эмили Фортуной, которая является одним из главных разработчиков Flutter), чтобы лучше понять Slivers.
Medium: Slivers, Demystific
Но потом нашел этоYoutube видео, которое в основном использовало ваш код, поэтому я выбрал этот, а не пытался выяснить каждую мелочь о Slivers.
Youtube: Использование контроллеров Tab и Scroll и NestedScrollView в Dart's Flutter Framework
Оказывается, вы были на правильном пути со своим кодом.Вы можете использовать SliverAppBar
в NestedScrollView
(это было не так в прошлый раз, когда я пытался), но я сделал несколько изменений.Это я объясню после моего кода:
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo'),
);
}
}
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 /*<-- This is for the controllers*/ {
TabController _tabController; // To control switching tabs
ScrollController _scrollViewController; // To control scrolling
List<String> items = [];
List<Color> colors = [Colors.red, Colors.green, Colors.yellow, Colors.purple, Colors.blue, Colors.amber, Colors.cyan, Colors.pink];
Random random = new Random();
Color getRandomColor() {
return colors.elementAt(random.nextInt(colors.length));
}
@override
void initState() {
super.initState();
_tabController =TabController(vsync: this, length: 2);
_scrollViewController =ScrollController();
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
_scrollViewController.dispose();
}
@override
Widget build(BuildContext context) {
// Init the items
for (var i = 0; i < 100; i++) {
items.add('Item $i');
}
return SafeArea(
child: NestedScrollView(
controller: _scrollViewController,
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text("WhatsApp using Flutter"),
floating: true,
pinned: false,
snap: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
child: Text("Colors"),
),
Tab(
child: Text("Chats"),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
controller: _tabController,
children: <Widget>[
ListView.builder(
itemBuilder: (BuildContext context, int index) {
Color color = getRandomColor();
return Container(
height: 150.0,
color: color,
child: Text(
"Row $index",
style: TextStyle(
color: Colors.white,
),
),
);
},
//physics: NeverScrollableScrollPhysics(), //This may come in handy if you have issues with scrolling in the future
),
ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Material(
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blueGrey,
),
title: Text(
items.elementAt(index)
),
),
);
},
//physics: NeverScrollableScrollPhysics(),
),
],
),
),
);
}
}
Хорошо, так далее до объяснения.
Используйте StatefulWidget
Большинство виджетов во Флаттере будут с состоянием, но это зависит от ситуации.Я думаю, что в этом случае это лучше, потому что вы используете ListView
, который может измениться, когда пользователи добавляют или стирают разговоры / чаты.
SafeArea
, потому что этот виджетотлично.
Читайте об этом на Документы по флаттеру: SafeArea
Контроллеры
Сначала я думаю, что это была большая проблема, но, возможно, это было что-то еще.Но вы обычно должны создавать свои собственные контроллеры, если вы имеете дело с пользовательским поведением во Флаттере.Таким образом, я сделал _tabController
и _scrollViewController
(я не думаю, что я получил все функциональные возможности, то есть отслеживание позиций прокрутки между вкладками, но они работают для основ).Контроллер табуляции, который вы используете для TabBar
и TabView
, должен быть одинаковым.
Виджет Material
перед ListTile
Возможно, вы бы узнали об этом рано или поздно, но виджет ListTile
является виджетом Материала и поэтому требует «виджета предка материала» в соответствии с выводом, который я получил при первой попытке его визуализации.Так что я избавил тебя от крошечной головной боли.Я думаю, это потому, что я не использовал Scaffold
.(Просто имейте это в виду, когда вы используете виджеты материалов без виджетов предшественников материалов)
Надеюсь, это поможет вам начать работу, если вам нужна помощь, просто напишите мне или добавьте меня в свойGithub репо, и я посмотрю, что я могу сделать.
--- ОРИГИНАЛ ---
Я также ответил вам на Reddit, надеюсь, вы скоро увидите один из этих двух.
SliverAppBar Info
Ключевые свойства, которые вы хотите иметь с SliverAppBar:
floating: Whether the app bar should become visible as soon as the user scrolls towards the app bar.
pinned: Whether the app bar should remain visible at the start of the scroll view. (This is the one you are asking about)
snap: If snap and floating are true then the floating app bar will "snap" into view.
Все это взято из Flutter SliverAppBar Docs .У них есть много анимированных примеров с различными комбинациями плавающих, закрепленных и привязанных.
Так что для вас должно работать следующее:
SliverAppBar(
title: Text("Application"),
floating: true, // <--- this is required if you want the appbar to come back into view when you scroll up
pinned: false, // <--- this will make the appbar disappear on scrolling down
snap: true, // <--- this is required if you want the application bar to 'snap' when you scroll up (floating MUST be true as well)
bottom: new TabBar(
tabs: [ ... ], // <-- total of 2 tabs
),
),
ScrollView с SliverAppBar
Чтобы ответить на основной вопрос NestedScrollView
.Согласно документам (таким же, как указано выше) SliverAppBar
- это:
Панель приложения дизайна материала, которая интегрируется с CustomScrollView
.
Поэтомувы не можете использовать NestedScrollView
, вам нужно использовать CustomScrollView
. Это предназначено для использования Sliver
классов, но они могут использоваться в NestedScrollView
Ознакомьтесь с документами .