У меня есть приложение Flutter, и теперь я хочу сделать его веб-версию, когда я пытаюсь запустить его, веб-приложение занимает весь экран рабочего стола, что нарушает дизайн. Это код, который я использую
MediaQuery(
data: new MediaQueryData(),
child: MaterialApp(
home: ScreenUtilInit(
splitScreenMode: true,
designSize: const Size(390, 844),
minTextAdapt: true,
builder: (context, child) {
return MainHomePageN();
})))
Я хочу, чтобы веб-представление было похоже на высоту и ширину мобильного экрана, а оставшийся экран был черным. Итак, есть ли способ добиться этого, добавив ограничение в одном месте.
Я думаю, это должно сделать это:
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 390),
child: const ScreenUtilInit(
//...
),
);
В общем, просто обернуть все ваше приложение в SizedBox
, которое находится в Center
, должно работать, например
Center(
child: SizedBox(
height: 844,
width: 390,
child: MediaQuery(
...
)
)
)
Но я не знаком ScreenUtilInit
, и может случиться так, что его внутренняя работа не очень хорошо работает с этим решением.
Я уже пробовал, но это не помогло.
Это покажет мобильный дизайн в Интернете, отрегулировав ширину:
Код:
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() и добавил к ним некоторые условия.
Я полагаю, это то, чего вы пытаетесь достичь, но без дизайна/картинки/изображения это трудно понять.
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,
);
}
}
Я пытался добавить его, но все равно занимает весь экран.