Исправление ширины экрана для флаттер-паутины

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

MediaQuery(
    data: new MediaQueryData(),
    child: MaterialApp(
        home: ScreenUtilInit(
            splitScreenMode: true,
            designSize: const Size(390, 844),
            minTextAdapt: true,
            builder: (context, child) {
              return MainHomePageN();
            })))

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
165
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Я думаю, это должно сделать это:

ConstrainedBox(
  constraints: const BoxConstraints(maxWidth: 390),
  child: const ScreenUtilInit(
  //...
  ),
);

Я пытался добавить его, но все равно занимает весь экран.

Malay Agrawal 12.04.2023 22:04

В общем, просто обернуть все ваше приложение в SizedBox, которое находится в Center, должно работать, например

Center(
  child: SizedBox(
    height: 844,
    width: 390,
    child: MediaQuery(
      ...
    )
  )
)

Но я не знаком ScreenUtilInit, и может случиться так, что его внутренняя работа не очень хорошо работает с этим решением.

Я уже пробовал, но это не помогло.

Malay Agrawal 18.04.2023 10:39
Ответ принят как подходящий

Это покажет мобильный дизайн в Интернете, отрегулировав ширину:

Код:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'dart:ui' as ui;

class MobileDesignWidget extends StatelessWidget {
  final maxWebAppRatio = 4.8 / 6.0;
  final minWebAppRatio = 9.0 / 16.0;

  final Widget child;

  MobileDesignWidget({
    required this.child,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxHeight < constraints.maxWidth) {
          return Container(
            alignment: Alignment.center,
            child: ClipRect(
              child: AspectRatio(
                aspectRatio: getCurrentWebAppRatio(),
                child: child,
              ),
            ),
          );
        }
        return child;
      },
    );
  }

  double getCurrentWebAppRatio() {
    double currentWebAppRatio = minWebAppRatio;

    // Fixed ratio for Web
    var physicalScreenSize = ui.window.physicalSize;
    var physicalWidth = physicalScreenSize.width;
    var physicalHeight = physicalScreenSize.height;

    currentWebAppRatio = physicalWidth / physicalHeight;
    if (currentWebAppRatio > maxWebAppRatio) {
      currentWebAppRatio = maxWebAppRatio;
    } else if (currentWebAppRatio < minWebAppRatio) {
      currentWebAppRatio = minWebAppRatio;
    }
    return currentWebAppRatio;
  }
}

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

  @override
  Widget build(BuildContext context) {
    return MobileDesignWidget(
      child: /*your scaffold*/,
    );
  }

Спасибо, это сработало, я обернул все свои леса в ScreenWidthWidget() и добавил к ним некоторые условия.

Malay Agrawal 22.04.2023 09:28

Я полагаю, это то, чего вы пытаетесь достичь, но без дизайна/картинки/изображения это трудно понять.

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

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: kIsWeb
          ? Row(children: const [
              Spacer(),
              SizedBox(
                width: 390,
                child: YourWidget(...),
              ),
              Spacer(),
            ])
          : ScreenUtilInit(...),
    );
  }
}

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

Я думаю, что есть много способов добиться этого. Но чтобы адаптировать только веб-код и изменить минимум исходного кода, давайте попробуем с LayoutBuilder. У нас нет подсказок о вашем исходном коде, но добавьте переменную в конструктор ваших экранов. Они будут двойными? ширина и двойной? высота. Хитрость будет заключаться в следующем: если мы находимся в Интернете, у нас будет Layoutbuilder, передающий пользовательскую ширину и пользовательскую высоту. Итак, в initState ваших экранов проверьте:

@override


void initState() {
    if (widget.width != null) {
      yourOriginalWidthVariable = widget.width; //receive the custom size from layoutBuilder simulating desirable screen size 
      yourOriginalHeightVariable = widget.height;
    } else {
      yourOriginalWidthVariable = MediaQuery.of(context).size.width; //receive the screen size
      yourOriginalWidthVariable = MediaQuery.of(context).size.height;
    }
    super.initState();
  }

При этом мы настроили размер экрана. Теперь нам просто нужно вставить черную черту с каждой стороны. Итак, в ваш основной (или в корневую точку) добавьте LayoutBuilder. Я дам вам образец. Допустим, вы поместите его в свой файл main.dart:

return MaterialApp(
    onGenerateRoute: route.controller,
    initialRoute: route.indexPage,
    title: 'your app name',
    debugShowCheckedModeBanner: false,
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      useMaterial3: true,
    ),
    home: LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
      width = constraints.maxWidth;
      height = constraints.maxHeight;
      if (kIsWeb){
        width = width&*0.25;// adjust to better simulate the mobile screen. Needs to test
        height = height*0.9; //the same
      }
      return SizedBox(
       height: constraints.maxHeight; //ensure allways max height
       width: constraints.maxWidth;// ensure always max width
       child: Row(
        children: [
         Expanded(
          child: Container(
          color: Colors.black)
         ),
         SizedBox(
         width:width, //will receive the size of your desire
         child: yourIndexScreen(width: kisweb ? width : null, height: kisWeb ? height : null); //pass the width and height if is web
        ),
         Expanded(
          child: Container(
          color: Colors.black)
         ),
        ]           
      ),
      );
      
    },
  ),
  );

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

Очень сложным решением было бы использовать auto_route вот так:

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

  @override
  Widget build(BuildContext context) {
    return const SizedBox(
      width: 500,
      child: AutoRouter(),
    );
  }
}

Тогда в файле маршрутизации у вас будет что-то вроде этого:

@MaterialAutoRouter(
  replaceInRouteName: 'Screen,Route',
  routes: <AutoRoute>[
    AutoRoute(
      path: '/',
      children: [
        AutoRoute(
          path: '',
          page: LandingScreen,
        ),
        ... other screens and stuff
      ],
      page: WidgetAtTheTopOfTheApp,
    ),
  ],
)

Пожалуйста, проверьте документацию пакета, потому что я еще не тестировал этот код.

Другой подход заключается в простом создании виджета нужного размера, который вы размещаете в верхней части каждого каркаса. (Это потребует немного больше рефакторинга)

class WidgetAtTheTopOfTheScaffold extends StatelessWidget {
  final Widget child;
  const WidgetAtTheTopOfTheScaffold({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 500,
      child: child,
    );
  }
}

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