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

좋은 웹페이지 즐겨찾기