这可能是一个很容易解决的问题,但是我认为无论如何我还是要问:CustomScrollView
内是否有任何方法可以固定一个小部件?我想使用CustomScrollView
来支持应用栏中的灵活空间,但是我需要使输入小部件固定在屏幕底部。我尝试使用给定的小部件将CustomScrollView
嵌套到Column
中,但似乎不起作用:
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CustomScrollView(
slivers: <Widget>[
_buildAppBar(), // Returns a SliverAppBar
_buildMessages(), // Returns a StreamBuilder that returns a SliverList
],
),
MessageInputWidget(), // Input that needs to stay fixed
],
);
}
这是_buildMessages()方法:
Widget _buildMessages(BuildContext context) {
return StreamBuilder<List<Message>>(
stream: widget.classroom.messages(),
builder: (context, snapshot) {
print('[DEBUG] Building chat with updated message stream...');
if (!snapshot.hasData || snapshot.data == null) {
return Center(
child: CircularProgressIndicator(),
);
}
_messages = snapshot.data;
print('[DEBUG] Building ${_messages.length} messages...');
return SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
if (index == _messages.length) {
return _buildHeader(context);
}
return MessageWidget(
message: _messages[index],
isReceived: _user.id != _messages[index].sentBy.id,
showUser: (index ==
0) || // Show _avatar if it's the first msg
(index >=
1 && // Or if it's a different _user than the last
!(_messages[index].sentBy.id ==
_messages[index - 1].sentBy.id)),
);
},
childCount: _messages.length,
),
);
});
}
有什么建议吗?我找到了一些examples,但是它可以构建整个CustomScrollView
,而我只想在每次获得新快照时都构建SliverList
。
有什么建议吗?
答案 0 :(得分:0)
是的,但是您没有将其放入自定义滚动中,因此使用了堆栈小部件。它将分层的小部件放在屏幕上。下面是您之前提出的内容。为了使窗口小部件位于底部,必须使用带有展开的列。
Stack(
children: <Widget>[
yourStreamBuilder(),
Column(
children: <Widget>[
Expanded(child: Container()),
Container(
width: MediaQuery.of(context).size.width,
height: 44,
color: Colors.red,
child: Text("Your bottom container"),
)
],
),
],
)
完整示例:
import 'package:flutter/material.dart';
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 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> {
Map<String, dynamic> tocando = {};
String ultimoTocando;
Future<List<Map<String, dynamic>>> listaDeMusicas() async {
return List<Map<String, dynamic>>.generate(
1200,
(i) => {"audio": "musica $i", "idUnico": "$i"},
);
}
tocar(String musica) {
print("tocando $musica ");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
yourStreamBuilder(),
Column(
children: <Widget>[
Expanded(child: Container()),
Container(
width: MediaQuery.of(context).size.width,
height: 44,
color: Colors.red,
child: Text("Your bottom container"),
)
],
),
],
));
}
Widget yourStreamBuilder() {
return FutureBuilder<List<Map<String, dynamic>>>(
future: listaDeMusicas(),
initialData: [],
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var item = snapshot.data[index];
if (tocando[item["idUnico"]] == null)
tocando[item["idUnico"]] = false;
return Row(
children: <Widget>[
IconButton(
icon: Icon(
tocando[item["idUnico"]] ? Icons.stop : Icons.play_arrow),
onPressed: () {
setState(() {
if (ultimoTocando != null) {
tocando[ultimoTocando] = false;
}
if (ultimoTocando != item["idUnico"]) {
tocando[item["idUnico"]] = !tocando[item["idUnico"]];
}
if (tocando[item["idUnico"]]) {
tocar(item["audio"]);
}
});
ultimoTocando = item["idUnico"];
},
),
Text(item["audio"]),
],
);
},
);
},
);
}
}