Как растянуть изображение, чтобы оно соответствовало всему фону (100% высоты x 100% ширины) в Flutter?

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

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

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

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,
  ],
);

19 ответов

Неправильный подход здесь.

Вместо этого используйте DecoratedBox. Или атрибут художественного оформления /foregroundDecoration Контейнера (который тогда использует DecoratedBox).

return new Container(
  decoration: const BoxDecoration(
    image: const DecorationImage(
      fit: BoxFit.fill,
      image: const AssetImage("images/common/toto.png"),
    ),
  ),
  child: new Text("Hello"),
);

Следующее будет соответствовать изображению до 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
    


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

    fit: BoxFit.fitHeight
    


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

    fit: BoxFit.fitWidth
    


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

    fit: BoxFit.cover
    


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

    fit: BoxFit.contain
    

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

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

Для меня при разработке для Интернета отлично работает следующее:

      Image(
  image: AssetImage('lib/images/portadaSchamann5.png'),
  alignment: Alignment.center,
  height: double.infinity,
  width: double.infinity,
  fit: BoxFit.fill,
),

Возможно, это не совсем то, что искал OP, но на этой странице я обнаружил себя после поиска проблемы, поэтому поделитесь ею со всеми, у кого есть аналогичная проблема:)

Стека fitсвойство помогло мне удовлетворить мои потребности. В противном случае изображение внутри (OctoImage в моем случае) было дополнено и предоставлено другое Image.fit значения не дали никакого эффекта.

Stack(
  fit: StackFit.expand, 
  children: [
    Image(
      image: provider,
      fit: BoxFit.cover,
    ),
    // other irrelevent children here
  ]
);

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

//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

Лучший пример для этого вопроса я нашел на этой странице: https://flutterbeads.com/set-background-image-in-flutter/

Используя BoxDecoration и DecorationImage:

      Container(
  constraints: BoxConstraints.expand(),
  decoration: const BoxDecoration(
    image: DecorationImage(
        image: AssetImage("assets/images/cat2.jpg"), 
        fit: BoxFit.cover),
  )

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

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

Это должно работать,

Image.asset('assets/bg.jpg', подходит: BoxFit.cover,),

Ни один из приведенных выше ответов не помог мне. И поскольку нет принятого ответа, я обнаружил, что следующее расширенное изображение от горизонтального края до горизонтального края:

Container ( width: MediaQuery
                    .of(context)
                    .size
                    .width,
                child: 
                  Image.network(my_image_name, fit: BoxFit.fitWidth )
              )

Посетите https://youtu.be/TQ32vqvMR80 ИЛИ

Например, если у родительского ограничителя высота: 200, тогда

Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: NetworkImage('url'),
                fit: BoxFit.cover,
              ),
            ),
          ),

Это будет работать, если вы хотите добавить подходящее фоновое изображение во Flutter:

      class Myname extends StatelessWidget {
  const Myname({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Container(
          decoration: const BoxDecoration(
            image: DecorationImage(
              image: AssetImage("assets/aj.jpg"),
              fit: BoxFit.cover,
            ),
          ),
          child: Scaffold(
            backgroundColor: Colors.transparent,
            body: Column(),
          ),
        ),
      ),
    );
  }
}

Теперь вы можете добавить остальные вещи внутриColumn()

Я установил ширину и высоту контейнера на double.infinity вот так:

      Container(
        width: double.infinity,
        height: double.infinity,
        child: //your child
)

Я столкнулся с проблемами только с FittedBox поэтому я завернул свое изображение в LayoutBuilder:

      LayoutBuilder( 
   builder: (_, constraints) => Image(
      fit: BoxFit.fill,
      width: constraints.maxWidth,
      image: AssetImage(assets.example),
   ),
)

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

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

Для меня использование Image(fit: BoxFit.fill ...) работал в ограниченном контейнере.

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

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

Это сработало для меня

class _SplashScreenState extends State<SplashScreen> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: FittedBox(
        child: Image.asset("images/my_image.png"),
        fit: BoxFit.fill,
      ),);
  }
}

Я не нашел ответа в этом посте, но нашел исправление:

              Positioned(
            bottom: 0,
            top: 0,
            child: Image.asset(
          'assets/images/package_bg.png',
        )),

Этот код делает изображение подходящим по высоте в стеке.

Другие вопросы по тегам