Колонка флаттера с расширяющимся виджетом внутри вида прокрутки

#flutter #dart #flutter-layout

Вопрос:

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

Что-то вроде этого

прокрутка

когда содержимое больше экрана, оно должно прокручиваться

сгибание без прокрутки

когда содержимое меньше экрана, сгибайтесь посередине

Я попробовал несколько различных подходов, найденных на SO, но не могу понять, как заставить это работать. Если singleChildScrollView дать Column бесконечную высоту, Flexible то возникнет ошибка, так как она неограниченна.

Код на данный момент

 import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.grey,
        child: SafeArea(
            child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) => SingleChildScrollView(
              scrollDirection: Axis.vertical,
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.greenAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pinkAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pink.shade100,
                        margin: EdgeInsets.all(8),
                        child: TextField()),
                    Flexible(
                      child: Container(
                          alignment: Alignment.center,
                          color: Colors.blueAccent,
                          margin: EdgeInsets.all(8),
                          child: Text('Flex')),
                    ),
                    Container(
                        alignment: Alignment.center,
                        height: 100,
                        width: 250,
                        color: Colors.redAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Footer')),
                  ])),
        )),
      ),
    );
  }
}
 

Ответ №1:

После долгих проб и ошибок и безуспешного использования таких вещей, как LayoutBuilder , и IntrinsicHeight я, наконец, разработал решение для варианта использования, который я использую CustomScrollView , и вызвал Sliver виджет SilverFillRemaining .

 import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.grey,
        child: SafeArea(
            child: CustomScrollView(
          slivers: [
            SliverFillRemaining(
              hasScrollBody: false,
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: double.infinity,
                        color: Colors.greenAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pinkAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pink.shade100,
                        margin: EdgeInsets.all(8),
                        child: TextField()),
                    Flexible(
                      fit: FlexFit.tight,
                      child: Container(
                          alignment: Alignment.center,
                          color: Colors.blueAccent,
                          margin: EdgeInsets.all(8),
                          child: Text('Flex')),
                    ),
                    Container(
                        alignment: Alignment.center,
                        height: 100,
                        width: 250,
                        color: Colors.redAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Footer')),
                  ]),
            ),
          ],
        )),
      ),
    );
  }
}
 

Надеюсь, это поможет кому-нибудь еще с аналогичным вариантом использования