Используя Stack в flutter, как мне сохранить согласованный стиль при больших размерах экрана?

#flutter #dart #flutter-layout

Вопрос:

У меня возникли проблемы с созданием пользовательского интерфейса в flutter. По сути , это экран приветствия с элементами SVG, сложенными вместе в a Stack и слегка расположенными с помощью Positioned . Я могу построить это для меньшего размера экрана здесь (iPhone 11).:

введите описание изображения здесь

Однако при сборке для более крупного устройства (iPad Mini и выше) это является результатом:

введите описание изображения здесь

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

Вот мой код:

   Widget _body(BuildContext context) {
    return Container(
      color: Color(0xFFE5E5E5),
      width: double.infinity,
      child: _buildWelcomeImage(context),
    );
  }

  Widget _buildWelcomeImage(BuildContext context) {
    final width = MediaQuery.of(context).size.width;
    final height = MediaQuery.of(context).size.height;
    var blockSizeHorizontal = (width / 100);
    var blockSizeVertical = (height / 100);

    return Stack(
      children: [
        Positioned.fill(
          top: blockSizeVertical * 7,
          child: Align(
            alignment: Alignment.topCenter,
            child: SvgPicture.asset(
              'assets/svg/login.svg',
              alignment: Alignment.topCenter,
              width: width,
              fit: BoxFit.fill,
            ),
          ),
        ),
        Positioned(
            top: blockSizeVertical * 6,
            left: blockSizeHorizontal * 3,
            child: Text('Logo here')
        Positioned.fill(child: _buildWelcomeActions(context)),
      ],
    );
  }

  Widget _buildWelcomeActions(BuildContext context) {
    final width = MediaQuery.of(context).size.width;
    final height = MediaQuery.of(context).size.height;
    var blockSizeVertical = (height / 100);

    return Align(
      alignment: Alignment.bottomCenter,
      child: FractionallySizedBox(
        heightFactor: 0.4,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(90),
            ),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                'copy copy',
                style: TextStyle(
                  fontSize: 38,
                  height: 1.2,
                  fontWeight: FontWeight.w600,
                ),
              ),
              Text(
                'copy.',
                style: TextStyle(
                  fontSize: 38,
                  color: AppColors.Primary,
                  height: 1.2,
                  fontWeight: FontWeight.w600,
                ),
              ),
              Container(
                padding: EdgeInsets.only(
                  top: blockSizeVertical * 2,
                  bottom: blockSizeVertical * 4,
                ),
                child: Text(
                  'copy copy copy',
                  style: GoogleFonts.workSans(
                    textStyle: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.w400,
                    ),
                  ),
                ),
              ),
              _buildButtons(context),
            ],
          ),
        ),
      ),
    );
  }
 

Я что-то делаю не так?

Комментарии:

1. Попробуйте уменьшить высоту на широком экране

Ответ №1:

Вы не делаете ничего плохого сами по себе, но из-за того, что соотношение сторон между телефоном и столом разное, когда вы используете BoxFit.fill для подгонки SVG, оно будет масштабироваться, чтобы «заполнить» доступное пространство, что приведет к другому позиционированию.

Любые мои предложения изменят ваш дизайн:

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

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

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

Комментарии:

1. Какова была бы альтернатива?

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