Как растянуть изображение в соответствии со всем фоном (100% высота х 100%) во Флаттере?

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

CSS имеет понятие процента, поэтому я мог бы просто установить высоту и ширину на 100%. Но это не похоже, что у Флаттера есть эта концепция, и это плохо, чтобы просто кодировать высоту и ширину, поэтому я застрял.

Вот что у меня (я использую стек, так как у меня есть что-то на переднем плане изображения):

Widget background = new Container(
  height: // Not sure what to put here!
  width: // Not sure what to put here!
  child: new Image.asset(
    asset.background,
    fit: BoxFit.fill, // I thought this would fill up my Container but it doesn't
  ),
);

return new Stack(
  children: <Widget>[
    background,
    foreground,
  ],
);

Ответы

Ответ 1

Чтобы сделать Image заполнением его родителя, просто оберните его в FittedBox:

FittedBox(
  child: Image.asset('foo.png'),
  fit: BoxFit.fill,
)

FittedBox здесь растянет изображение, чтобы заполнить пространство. (Обратите внимание, что эта функциональность раньше предоставлялась BoxFit.fill, но API тем временем изменился так, что BoxFit больше не предоставляет эту функциональность. FittedBox должен работать в качестве замены, не нужно вносить никаких изменений в аргументы конструктора.)


В качестве альтернативы, для сложных декораций вы можете использовать Container вместо Image - и использовать поля decoration/foregroundDecoration.

Чтобы Container стал его родителем, он должен:

  • не иметь ребенка
  • иметь свойство alignment не null

Вот пример, который объединяет два изображения и Text в одном Container, принимая 100% ширину/высоту его родителя:

enter image description here

Container(
  foregroundDecoration: const BoxDecoration(
    image: DecorationImage(
        image: NetworkImage(
            'https://p6.storage.canalblog.com/69/50/922142/85510911_o.png'),
        fit: BoxFit.fill),
  ),
  decoration: const BoxDecoration(
    image: DecorationImage(
        alignment: Alignment(-.2, 0),
        image: NetworkImage(
            'http://www.naturerights.com/blog/wp-content/uploads/2017/12/Taranaki-NR-post-1170x550.png'),
        fit: BoxFit.cover),
  ),
  alignment: Alignment.bottomCenter,
  padding: EdgeInsets.only(bottom: 20),
  child: Text(
    "Hello World",
    style: Theme.of(context)
        .textTheme
        .display1
        .copyWith(color: Colors.white),
  ),
),

Ответ 2

Следующее будет соответствовать изображению до 100% ширины контейнера, в то время как высота постоянна. Для локальных активов используйте AssetImage

Container(
  width: MediaQuery.of(context).size.width,
  height: 100,
  decoration: BoxDecoration(
    image: DecorationImage(
      fit: BoxFit.fill,
      image: NetworkImage("https://picsum.photos/250?image=9"),
    ),
  ),
)

Режимы заполнения изображения:

  • Заполнить - изображение растянуто

    fit: BoxFit.fill
    

    enter image description here


  • Подогнать высоту - изображение остается пропорциональным, при этом отображается полная высота изображения (возможно переполнение)

    fit: BoxFit.fitHeight
    

    enter image description here


  • Подогнать ширину - изображение остается пропорциональным, при этом отображается полная ширина изображения (возможно переполнение)

    fit: BoxFit.fitWidth
    

    enter image description here


  • Cover - изображение сохраняется пропорционально, обеспечивает максимальное покрытие контейнера (возможно переполнение)

    fit: BoxFit.cover
    

    enter image description here


  • Содержать - изображение сохраняется пропорциональным, минимально возможным, уменьшит его размер, если необходимо отобразить все изображение

    fit: BoxFit.contain
    

    enter image description here

Ответ 3

Внутри вашего стека вы должны обернуть свой background виджет в Positioned.fill.

return new Stack(
  children: <Widget>[
    new Positioned.fill(
      child: background,
    ),
    foreground,
  ],
);

Ответ 4

Я думаю, что для вашей цели Flex может работать лучше, чем Container():

new Flex(
    direction: Axis.vertical,
    children: <Widget>[
      Image.asset(asset.background)
    ],
   )

Ответ 5

Для заполнения я иногда использую SizedBox.expand

Ответ 6

Попробуйте установить contentPadding

ListTile(
  contentPadding: EdgeInsets.all(0.0),
  ...
)

Ответ 7

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

//gets the screen width and height
double Width = MediaQuery.of(context).size.width;
double Height = MediaQuery.of(context).size.height;

Widget background = new Image.asset(
  asset.background,
  fit: BoxFit.fill,
  width: Width,
  height: Height,
);

return new Stack(
  children: <Widget>[
    background,
    foreground,
  ],
);

Вы также можете использовать ширину и высоту для определения размера других объектов в зависимости от размера экрана.

Пример: width: Height/2, height: Height/2//using height for both keeps aspect ratio