Flutter에서 반응형 앱을 만드는 방법
민감도
MediaQuery를 사용하는 반응형 모바일 앱
소개
앱을 반응형으로 만드는 것은 모든 개발자에게 매우 중요합니다. MediaQuery를 사용하면 모든 화면 크기에 반응하는 앱을 만들 수 있습니다.
1 단계
먼저 장치 크기 -너비와 높이를 알아내는 방법을 찾아야 합니다.
이 인쇄 문을 사용하면 터미널에서 장치 크기를 얻을 수 있습니다.
print("Height: ${MediaQuery.of(context).size.height}, Width: ${MediaQuery.of(context).size.width}");
참고:- 높이와 너비를 찾는 데 이 방법을 사용하지 않으려면 기본값을 사용할 수 있습니다.
// Default values if you don't know about height or width of your screen
double deviceHeight = 690;
double deviceWidth = 360;
2 단계
lib 폴더에 responsive.dart 파일 생성
이 코드를 파일에 넣으십시오.
import 'dart:math';
import 'package:flutter/material.dart';
@immutable
class Responsive {
// Device Height = 875.428
// Device Width = 411.428
final BuildContext context;
final double deviceHeight;
final double deviceWidth;
const Responsive({
required this.context,
required this.deviceHeight,
required this.deviceWidth,
});
// general size
Size get size => MediaQuery.of(context).size;
// responsive width
double setWidth({required double width}) {
return MediaQuery.of(context).size.width / (deviceWidth / width);
}
// responsive height
double setHeight({required double height}) {
return MediaQuery.of(context).size.height / (deviceHeight / height);
}
// responsive font based on Width - it works but not a good solution
// double setFontSize({required double fontSize}) {
// return size.width / (deviceWidth / fontSize);
// }
// don't use it
double setTextScaleFactor({required double textScaleFactor}) {
return MediaQuery.of(context).textScaleFactor / textScaleFactor;
}
// remove padding all
MediaQueryData removeAllPadding() => MediaQuery.of(context).removePadding(
removeLeft: true, removeRight: true, removeBottom: true, removeTop: true);
// set devicePixel ration
double setDevicePixelRatio() => MediaQuery.of(context).devicePixelRatio;
// responsive bottom padding
double setBottomPadding({required double padding}) {
return MediaQuery.of(context).padding.bottom + padding;
}
// responsive Left Padding
double setLeftPadding({required double padding}) {
return MediaQuery.of(context).padding.left + padding;
}
// responsive right padding
double setRightPadding({required double padding}) {
return MediaQuery.of(context).padding.right + padding;
}
// responsive top padding
double setTopPadding({required double padding}) {
return MediaQuery.of(context).padding.top + padding - 20;
}
// set padding from all sides
double setPadding({required double padding}) {
double bottom = MediaQuery.of(context).padding.bottom;
double top = MediaQuery.of(context).padding.top;
double left = MediaQuery.of(context).padding.left;
double right = MediaQuery.of(context).padding.right;
return (bottom + top + left + right) + padding;
}
// responsive Bottom Margin
double setBottomMargin({required double margin}) {
return MediaQuery.of(context).padding.bottom + margin;
}
// responsive Left Margin
double setLeftMargin({required double margin}) {
return MediaQuery.of(context).padding.left + margin;
}
// responsive right Margin
double setRightMargin({required double margin}) {
return MediaQuery.of(context).padding.right + margin;
}
// responsive top Margin
double setTopMargin({required double margin}) {
return MediaQuery.of(context).padding.top + margin;
}
// set margin from all sides
double setMargin({required double margin}) {
double bottom = MediaQuery.of(context).padding.bottom;
double top = MediaQuery.of(context).padding.top;
double left = MediaQuery.of(context).padding.left;
double right = MediaQuery.of(context).padding.right;
return (bottom + top + left + right) + margin;
}
// responsive Width space - forExample in SizedBox
double setWidthSpace({required double width}) {
return MediaQuery.of(context).size.width / (deviceWidth / width);
}
// responsive height space - forExample in SizedBox
double setHeightSpace({required double height}) {
return MediaQuery.of(context).size.height / (deviceHeight / height);
}
// scaling the font size based on scale factor - use for scaling fontSize
double setFontSize({required double fontSize}) {
final double sWidth = MediaQuery.of(context).size.width;
final double sHeight = MediaQuery.of(context).size.height;
// if i divide the deviceHeight / sHeight.. than the font will adjust it's self inside box
// but in blow case it is working only the font size.
final scaleH = sHeight / deviceHeight;
final scaleW = sWidth / deviceWidth;
final double scale = max(scaleW, scaleH);
final textScaleFactor = MediaQuery.of(context).textScaleFactor;
return fontSize * scale * textScaleFactor;
}
double setHeightWithoutSafeArea({required double heightWithoutSafeArea}) {
EdgeInsets padding = MediaQuery.of(context).viewPadding;
double height = size.height;
return height -
(deviceHeight / heightWithoutSafeArea) -
padding.top -
padding.bottom;
}
double setWidthWithoutSafeArea({required double heightWithoutSafeArea}) {
EdgeInsets padding = MediaQuery.of(context).viewPadding;
double width = size.width;
return width -
(deviceHeight / heightWithoutSafeArea) -
padding.top -
padding.bottom;
}
double setHeightWithoutStatusBar({required double heightWithoutSafeArea}) {
EdgeInsets padding = MediaQuery.of(context).viewPadding;
double height = size.height;
return height - (deviceHeight / heightWithoutSafeArea) - padding.top;
}
double setHeightWithoutStatusBarToolbar(
{required double heightWithoutSafeArea}) {
EdgeInsets padding = MediaQuery.of(context).viewPadding;
double height = size.height;
return height -
(deviceHeight / heightWithoutSafeArea) -
padding.top -
kToolbarHeight;
}
// Use can use this to set Radius from all sides
// as well as from only one side
double setRadius({required double radius}) {
final double sWidth = MediaQuery.of(context).size.width;
final double sHeight = MediaQuery.of(context).size.height;
final scaleH = sHeight / deviceHeight;
final scaleW = sWidth / deviceWidth;
return radius * min(scaleW, scaleH);
}
// for different values such as the using this you can pass even a widget
getResponsiveValue({
dynamic forShortScreen,
dynamic forMediumScreen,
dynamic forLargeScreen,
dynamic forMobLandScapeMode,
dynamic forTabletScreen,
required BuildContext context,
}) {
if (isLargeScreen(context)) {
return forLargeScreen ?? forShortScreen;
} else if (isMediumScreen(context)) {
return forMediumScreen ?? forShortScreen;
} else if (isTabletScreen(context)) {
return forTabletScreen ?? forMediumScreen ?? forShortScreen;
} else if (isSmallScreen(context) && isLandScapeMode(context)) {
return forMobLandScapeMode ?? forShortScreen;
} else {
return forShortScreen;
}
}
isLandScapeMode(BuildContext context) {
if (MediaQuery.of(context).orientation == Orientation.landscape) {
return true;
} else {
return false;
}
}
static bool isLargeScreen(BuildContext context) {
return getWidth(context) > 1200;
}
static bool isSmallScreen(BuildContext context) {
return getWidth(context) < 800;
}
static bool isMediumScreen(BuildContext context) {
return getWidth(context) > 800 && getWidth(context) < 1200;
}
static bool isTabletScreen(BuildContext context) {
return getWidth(context) > 450 && getWidth(context) < 800;
}
// getting full width
static double getWidth(BuildContext context) =>
MediaQuery.of(context).size.width;
}
예시
import 'package:flutter/material.dart';
import 'package:responsiveness/responsive.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// -- this is my app screens that i was working on
// double deviceHeight = 875.428;
// double deviceWidth = 411.428;
// default size for every type of app
double deviceHeight = 690;
double deviceWidth = 360;
@override
Widget build(BuildContext context) {
// to set and orientation
Orientation currentOrientation = MediaQuery.of(context).orientation;
if (currentOrientation == Orientation.portrait) {
setState(() {
deviceHeight = MediaQuery.of(context).size.height;
});
} else {
setState(() {
deviceHeight = MediaQuery.of(context).size.width;
});
}
Responsive rs = Responsive(
context: context,
deviceHeight: deviceHeight,
deviceWidth: deviceWidth,
);
return Scaffold(
appBar: AppBar(
title: const Text("Responsiveness"),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: rs.setWidth(width: 100),
height: rs.setHeight(height: 200),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.all(
Radius.circular(rs.setRadius(radius: 20)))),
child: Text(
"H",
style: TextStyle(
fontSize: rs.setFontSize(fontSize: 20),
color: Colors.white),
),
),
SizedBox(
height: rs.setHeightSpace(height: 20),
),
Container(
width: 100,
height: 200,
decoration: const BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.all(Radius.circular(20))),
),
Container(
width: rs.setWidth(width: 100),
height: rs.setHeight(height: 200),
alignment: Alignment.center,
color: Colors.blue,
child: Text(
"ScalerPixel",
style: TextStyle(
fontSize: rs.setFontSize(fontSize: 20),
color: Colors.white),
),
),
Container(
width: 100,
height: 100,
alignment: Alignment.center,
color: rs.getResponsiveValue(
forLargeScreen: Colors.red,
forTabletScreen: Colors.pink,
forMediumScreen: Colors.green,
forShortScreen: Colors.yellow,
forMobLandScapeMode: Colors.blue,
context: context,
),
child: Text(
rs.getResponsiveValue(
context: context,
forLargeScreen: 'LargeScreen',
forShortScreen: 'ShortScreen',
forMediumScreen: 'MediumScreen',
forTabletScreen: 'Tablet',
forMobLandScapeMode: 'LandScape'),
),
),
],
),
),
);
}
}
정위
Orientation currentOrientation = MediaQuery.of(context).orientation;
if (currentOrientation == Orientation.portrait) {
setState(() {
deviceHeight = MediaQuery.of(context).size.height;
});
} else {
setState(() {
deviceHeight = MediaQuery.of(context).size.width;
});
}
LayoutBuilder, AspectRation, OrientationBuilder 및 Constraints와 같이 고려해야 하는 많은 요소와 플랫폼을 기반으로 처리해야 하는 몇 가지 사항이 있기 때문에 이것은 완벽한 솔루션이 아닙니다.
그러나 이것은 작업을 수행하는 가장 기본적이고 빠른 방법입니다. 도움이 되길 바랍니다.
GitHub 레포 - repo
Reference
이 문제에 관하여(Flutter에서 반응형 앱을 만드는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ayoubzulfiqar/how-to-make-responsive-app-in-flutter-2ij5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)