Лучший способ определить индивидуальную карту во Flutter

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

например

      return Card(child: Column(
  children: [
    Row(
      children: [
        Column( children: [
          Text('Riverside cafe...'),
          Ratingbar(),
        ],),
        ImageWidget(),
      ],
    ),
    Container(child: Text('Pubs & restaurants'), color : Colors.purple)
  ],

Полученные карты необходимо отобразить в listview и используя rows а также columns выше приводит к тому, что области имеют разный размер в зависимости от данных.

Мне кажется, что с помощью row а также columnможет быть не лучшим способом добиться этого. Есть ли способ лучше?

1 ответ

Что касается лучшего, полагаю, решать вам и вашему клиенту.

За все время, что я работаю с Flutter, я не встречал ничего похожего на CSS-сетку, которая отлично подходит для таких ситуаций. Ближайшим сравнением является StaggeredGrid (https://pub.dev/packages/flutter_staggered_grid_view), но он не предлагает такого большого контроля, как CSS-сетка, и, похоже, не совсем подходит для вашего варианта использования.

Строки, столбцы (и другие виджеты макета) могут выполнить свою работу:

Вот файл main.dart, создавший приведенный выше пример. Качество кода не идеальное, но, надеюсь, вы сможете достаточно хорошо за ним следить, и это поможет вам сделать то, что вам нужно.

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);

  static const String _title = 'Bespoke card example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Bespoke card example')),
      body: Center(
        child: Wrap(runSpacing: 10.0, children: [
          BespokeCard(title: 'Short name', width: 350),
          BespokeCard(
              title: 'Riverside Cafe with a really long name', width: 350)
        ]),
      ),
    );
  }
}

class BespokeCard extends StatelessWidget {
  final String title;
  final double width;
  BespokeCard({this.title, this.width});
  @override
  Widget build(BuildContext context) {
    Widget _restaurantNameContainer = Container(
      constraints: BoxConstraints(
        minHeight: 0,
        maxHeight: 120,
        maxWidth: (500.0 - 40 - 175 + 1),
        minWidth: (500.0 - 40 - 175 + 1),
      ),
      child: AutoSizeText(
        title,
        style: TextStyle(fontSize: 60),
        maxLines: 2,
        minFontSize: 10,
        stepGranularity: 0.1,
        overflow: TextOverflow.ellipsis,
      ),
    );
    Widget _rightSideSection = Container(
      width: 175,
      height: Size.infinite.height,
      child: Center(
        child: Icon(
          Icons.umbrella,
          size: 70,
        ),
      ),
    );
    Widget _topSection = Flexible(
      flex: 1,
      child: Row(
        children: [
          Flexible(
            fit: FlexFit.tight,
            flex: 3,
            child: Padding(
              padding: EdgeInsets.only(left: 40.0, top: 25.0),
              child: Column(
                children: [
                  Flexible(child: Container(), flex: 1),
                  _restaurantNameContainer,
                  Text('* * * * *', style: TextStyle(fontSize: 70)),
                ],
              ),
            ),
          ),
          _rightSideSection
        ],
      ),
    );

    Widget _bottomSection = Container(
        height: 70,
        width: Size.infinite.width,
        child: Center(
          child: Text('Pubs & Restaurants',
              style: TextStyle(color: Colors.white, fontSize: 40)),
        ),
        color: Colors.purple);

    Widget unfittedCard = Card(
        child: SizedBox(
      width: 500,
      height: 300,
      child: Column(
        mainAxisSize: MainAxisSize.max,
        children: [_topSection, _bottomSection],
      ),
    ));
    return Container(
        width: this.width,
        child: FittedBox(fit: BoxFit.fitWidth, child: unfittedCard));
  }
}


ЗАМЕТКИ:

  • Помните о свойстве flexFit (плотный или свободный): flexible/fit.htmlhttps://api.flutter.dev/flutter/widgets/F
  • Вы можете либо определить фиксированные соотношения со всеми гибкими возможностями, либо вы можете смешивать гибкие элементы с контейнерами / SizedBox, что у вас есть
  • Пакет auto_size_text отлично подходит для подобных ситуаций. (Добавлять auto_size_text: ^2.1.0 к вашим зависимостям)
  • Помните об ограничениях бокса. Мне нужно, чтобы текст заголовка с автоподстройкой размера мог расти в высоту, не помещаясь в большой контейнер.
  • Встроенная коробка действительно удобна и позволяет легко масштабировать при трепетании.
Другие вопросы по тегам