Как определить ширину и высоту изображения в Flutter?

Предположим, я объявил свое изображение в моем pubspec.yaml следующим образом:

  assets:
    - assets/kitten.jpg

И мой код флаттера таков:

void main() {
  runApp(
    new Center(
      child: new Image.asset('assets/kitten.jpg'),
    ),
  );
}

Теперь, когда у меня есть new Image.asset(), как мне определить ширину и высоту этого изображения? Например, я просто хочу распечатать изображение ширины и высоты.

(Это похоже на dart: ui. Класс Image имеет ширину и высоту, но не уверен, как перейти от виджета Image к dart: ui Image.)

Спасибо!

Ответ 1

ОБНОВЛЕННОЕ РЕШЕНИЕ:

С новой версией флаттера старое решение устарело. Теперь addListener нужен ImageStreamListener.

Widget build(BuildContext context) {
    Image image = new Image.network('https://i.stack.imgur.com/lkd0a.png');
    Completer<ui.Image> completer = new Completer<ui.Image>();
    image.image
      .resolve(new ImageConfiguration())
      .addListener(ImageStreamListener(ImageInfo info, bool _) { 
        completer.complete(info.image));
      })
    ...
    ...

ОРИГИНАЛЬНАЯ ВЕРСИЯ:

Если у вас уже есть виджет Image, вы можете прочитать ImageStream из него, вызвав resolve на его ImageProvider.

screenshot

import 'dart:ui' as ui;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(new MaterialApp(
    home: new MyHomePage(),
  ));
}

class MyHomePage extends StatelessWidget {

  Widget build(BuildContext context) {
    Image image = new Image.network('https://i.stack.imgur.com/lkd0a.png');
    Completer<ui.Image> completer = new Completer<ui.Image>();
    image.image
      .resolve(new ImageConfiguration())
      .addListener((ImageInfo info, bool _) => completer.complete(info.image));
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Image Dimensions Example"),
      ),
      body: new ListView(
        children: [
          new FutureBuilder<ui.Image>(
            future: completer.future,
            builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
              if (snapshot.hasData) {
                return new Text(
                  '${snapshot.data.width}x${snapshot.data.height}',
                  style: Theme.of(context).textTheme.display3,
                );
              } else {
                return new Text('Loading...');
              }
            },
          ),
          image,
        ],
      ),
    );
  }
}

Ответ 2

Вы можете resolve ImageProvider для получения ImageStream, а затем использовать addListener для уведомления, когда изображение будет готово.

screenshot

import 'dart:ui' as ui;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(new MaterialApp(
    home: new MyHomePage(),
  ));
}

class MyHomePage extends StatelessWidget {

  Future<ui.Image> _getImage() {
    Completer<ui.Image> completer = new Completer<ui.Image>();
    new NetworkImage('https://i.stack.imgur.com/lkd0a.png')
      .resolve(new ImageConfiguration())
      .addListener((ImageInfo info, bool _) => completer.complete(info.image));
    return completer.future;
  }

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Image Dimensions Example"),
      ),
      body: new Center(
        child: new FutureBuilder<ui.Image>(
          future: _getImage(),
          builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
            if (snapshot.hasData) {
              ui.Image image = snapshot.data;
              return new Text(
                '${image.width}x${image.height}',
                style: Theme.of(context).textTheme.display4);
            } else {
              return new Text('Loading...');
            }
          },
        ),
      ),
    );
  }
}

Ответ 3

Другие ответы кажутся слишком сложными, если вы просто хотите использовать ширину и высоту изображения в асинхронной функции. Вы можете получить разрешение изображения, используя flutter lib, вот так:

import 'dart:io';

File image = new File('image.png'); // Or any other way to get a File instance.
var decodedImage = await decodeImageFromList(image.readAsBytesSync());
print(decodedImage.width);
print(decodedImage.height);

Ответ 4

С новой версией флаттера старое решение не работает, например:

  image.image
  .resolve(new ImageConfiguration())
  .addListener((ImageInfo info, bool _) => completer.complete(info.image));

Ниже рабочая версия:

_image.image
    .resolve(new ImageConfiguration())
    .addListener(new ImageStreamListener((ImageInfo image, bool _) {
  completer.complete(image.image);
}));

Ответ 5

Создайте метод, например:

Future<Size> _calculateImageDimension() {
  Completer<Size> completer = Completer();
  Image image = Image.network("https://i.stack.imgur.com/lkd0a.png");
  image.image.resolve(ImageConfiguration()).addListener(
    ImageStreamListener(
      (ImageInfo image, bool synchronousCall) {
        var myImage = image.image;
        Size size = Size(myImage.width.toDouble(), myImage.height.toDouble());
        completer.complete(size);
      },
    ),
  );
  return completer.future;
}

И используйте это как:

_calculateImageDimension().then((size) => print("size = ${size}")); // 487.0,696.0