Flutter Transform.scale для дочерних виджетов не пропорционально масштабируется, почему? - PullRequest
0 голосов
/ 26 октября 2019

У меня есть базовый виджет флага, с кодом здесь:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: Flag(),
      ),
    );
  }
}

class Flag extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var scaleFactor = 1.0;

    final flag = Transform.scale(
      scale: scaleFactor,
      child: AspectRatio(
        aspectRatio: 5 / 3,
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(width: 2, color: Colors.black),
          ),
          child: Center(
            child: Container(
              height: 400,
              width: 150,
              color: Colors.purple,
            ),
          ),
        ),
      ),
    );

    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) => flag,
    );
  }
}

Это выглядит так:

stripe with correct ratio

ЕслиЯ изменяю scaleFactor на 0,5, он масштабируется, как и ожидалось:

stripe with correct ratio

Но если я поверну эмулятор в альбомную ориентацию, пропорции будут отключены:

stripe too small

Если я сделаю полосу пропорциональной альбомной ориентации (например, изменив ширину полосы на 250), она станет слишком большой в портретном режиме:

stripe too big

Как сделать так, чтобы фиолетовая полоса занимала одинаковое количество места независимо от размера устройства?

Флаг будет усложнятьсяпоэтому я не хочу использовать MediaQuery.of (context) .size, чтобы получить ширину устройства и рассчитать процент от этого значения для каждого дочернего виджета ...

Нужно ли сообщать моему виджету свой "канонический "размер? Нужно ли передавать scaleFactor каждому дочернему виджету?

Любые идеи очень ценятся:)

1 Ответ

1 голос
/ 29 октября 2019

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

1) Используйте виджет Row и Expanded для каждой части флага, с flex, равным единице. AspectRatio сохранит соотношение сторон фиксированным, поэтому пропорции должны оставаться одинаковыми для контейнеров. Так как по умолчанию коэффициент гибкости равен единице, вы также можете просто пропустить это. Если вам нужно, чтобы белые части были прозрачными, просто укажите цвет Colors.transparent.

class Flag extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var scaleFactor = 1.0;

    final flag = Transform.scale(
      scale: scaleFactor,
      child: AspectRatio(
        aspectRatio: 5 / 3,
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(width: 2, color: Colors.black),
          ),
          child: Row(
            children: <Widget>[
              Expanded(
                flex:1,
                child: Container(
                  color: Colors.white,
                ),
              ),
              Expanded(
                flex:1,
                child: Container(
                  color: Colors.purple,
                ),
              ),
              Expanded(
                flex:1,
                child: Container(
                  color: Colors.white,
                ),
              ),
            ],
          ),
        ),
      ),
    );

    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) => flag,
    );
  }
}

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

class Flag extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var scaleFactor = 1.0;

    final flag = Transform.scale(
      scale: scaleFactor,
      child: AspectRatio(
        aspectRatio: 5 / 3,
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(width: 2, color: Colors.black),
          ),
          child: Center(
            child: Transform(
              transform: Matrix4.diagonal3Values(0.33, 1.0, 1.0),
              alignment: Alignment.bottomCenter,
              child: Container(
                color: Colors.purple,
              ),
            ),
          ),
        ),
      ),
    );

    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) => flag,
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...