Использование StreamBuilder для создания SliverList для CustomScrollView

Это, вероятно, действительно легко исправить вопрос, но я подумал, что в любом случае могу задать его здесь: есть ли способ привязать виджет в 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,
            ),
          );
        });
  }

Какие-либо предложения? Я нашел несколько примеров, но это составляет всю CustomScrollView а я хочу строить SliverList только каждый раз, когда получаю новый снимок. Какие-либо предложения?


person Nicholas Chiang    schedule 19.11.2019    source источник


Ответы (1)


Да, но для этого вы не помещаете его в настраиваемую прокрутку, вы используете виджет стека. Он помещает многоуровневый виджет на экран. То, что идет ниже, вы ставите раньше. Чтобы ваш виджет располагался внизу, вы должны использовать столбец с развернутым.

  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"]),
              ],
            );
          },
        );
      },
    );
  }
}
person Claudio Castro    schedule 19.11.2019