9 분 소요

플러터의 주요 목표 중 하나는 단일 코드베이스에서 모든 플랫폼에서 great하게 보이고 느껴지는 앱을 개발할 수 있는 프레임워크를 만드는 것!

이것은 여러 가지 다른 크기의 화면에 앱이 나타날 수 있음을 의미한다. 시계부터 두 개의 화면을 가진 폴더폰, 고해상도 모니터까지도 말이당

이 시나리오를 설명하는데 사용되는 두 가지 개념은 “적응형adaptive ”과 “반응형responsive”이다. 이상적으로, 앱은 두 가지 모두가 되는 것이 좋겠지만, 이것이 정확히 무엇을 의미하는 걸까? 이 두 용어는 유사하지만 동일하진 않다.

The difference between an adaptive and a responsive app

Adaptive and responsive can be viewed as separate dimensions of an app: you can have an adaptive app that is not responsive, or vice versa. And, of course, an app can be both, or neither.

적응형과 반응형은 앱의 서로 다른 측면으로 볼 수 있다. 적응형이지만 반응형이 아닐 수도 있고, 반대도 가능하다. 물론, 앱은 둘 다 또는 둘 다 아닐 수도 있다.

Responsive: Typically, a responsive app has had its layout tuned for the available screen size. Often this means (for example), re-laying out the UI if the user resizes the window, or changes the device’s orientation. This is especially necessary when the same app can run on a variety of devices, from a watch, phone, tablet, to a laptop or desktop computer.

전형적으로, responsive 앱은 사용 가능한 화면 크기에 대해 레이아웃을 조정한다. 종종 사용자가 창의 크기를 조정하거나 기기의 방향을 변경할 때 UI를 다시 배치하는 것을 의미한다. 특히 동일 앱이 다양한 디바이스(시계, 폰, 태블릿, 노트북 또는 데스크톱 컴퓨터와 같은)에서 실행될 때 특히 필요하다.

  • ’layout’ 이란 페이지, 앱, 또는 인터페이스의 구조와 요소의 위치를 결정하는 과정을 의미한다.
  • ‘interface’란 두 가지 다른 시스템 또는 장치 간에 상호 작용하는 곳 또는 방법을 나타낸다.

Adaptive: Adapting an app to run on different device types, such as mobile and desktop, requires dealing with mouse and keyboard input, as well as touch input. It also means there are different expectations about the app’s visual density, how component selection works (cascading menus vs bottom sheets, for example), using platform-specific features (such as top-level windows), and more.

다른 기기 유형에서 실행되도록 앱을 적응하는 것(adaptive)은 마우스나 키보드 입력과 터치 입력을 처리해야 함을 의미한다. 이것은 앱의 시각적인 밀도, 구성 요소 선택 방식(캐스캐이딩 메뉴 vs 화면 하단 시트), 플랫폼별 기능 사용 등 기타 여러 가지 측면에서 다른 기대가 있음을 의미한다.

Creating a responsive Flutter app

Flutter allows you to create apps that self-adapt to the device’s screen size and orientation.

플러터는 디바이스의 화면 크기와 방향에 자동으로 적응하는 앱을 만들 수 있게 한다.

There are two basic approaches to creating Flutter apps with responsive design:

반응형 디자인을 사용하여 플러터 앱을 만드는 두 가지 접근 방식은 다음과 같다.

Use the [LayoutBuilder](https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html) class

From its [builder](https://api.flutter.dev/flutter/widgets/LayoutBuilder/builder.html) property, you get a [BoxConstraints](https://api.flutter.dev/flutter/rendering/BoxConstraints-class.html) object. Examine the constraint’s properties to decide what to display. For example, if your [maxWidth](https://api.flutter.dev/flutter/rendering/BoxConstraints/maxWidth.html) is greater than your width breakpoint, return a [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html) object with a row that has a list on the left. If it’s narrower, return a [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html) object with a drawer containing that list. You can also adjust your display based on the device’s height, the aspect ratio, or some other property. When the constraints change (for example, the user rotates the phone, or puts your app into a tile UI on Android), the build function runs.

첫 번째는 LayoutBuilder 클래스를 사용하는 것인데, builder 속성에서 BoxConstraints 객체를 가져올 수 있다. 제약 조건의 속성을 검사하여 표시할 내용을 결정한다.

예를 들어, maxWidth 가 너비 중단점보다 크면, 왼쪽에 목록이 있는 행이 있는 Scaffold 객체를 반환한다. 반대라면, 리스트를 포함하는 drawer가 있는 Scaffold 객체를 반환한다. 또한 기기의 높이, 종횡비, 다른 속성에 따라 화면에 어떻게 표시될지를 조정할 수 있다. 제약 조건이 변경되면(사용자가 폰을 회전하거나, Aos에서 앱을 타일 ui로 변경하면), 빌드 함수가 실행된다.

Use the [MediaQuery.of()](https://api.flutter.dev/flutter/widgets/MediaQuery/of.html) method in your build functions

This gives you the size, orientation, etc, of your current app. This is more useful if you want to make decisions based on the complete context rather than on just the size of your particular widget. Again, if you use this, then your build function automatically runs if the user somehow changes the app’s size.

MediaQuery.of() 를 통해 현재 앱의 크기, 방향 등을 얻을 수 있다. 이 방법은 특정 위젯의 크기 뿐만 아니라 완전한 context 기반으로 결정하는 경우에 유용하다. 만약 유저가 앱의 크기를 어떻게 변경하든 빌드 함수가 자동으로 실행된다.

Other useful widgets and classes for creating a responsive UI:

  • [AspectRatio](https://api.flutter.dev/flutter/widgets/AspectRatio-class.html)
  • [CustomSingleChildLayout](https://api.flutter.dev/flutter/widgets/CustomSingleChildLayout-class.html)
  • [CustomMultiChildLayout](https://api.flutter.dev/flutter/widgets/CustomMultiChildLayout-class.html)
  • [FittedBox](https://api.flutter.dev/flutter/widgets/FittedBox-class.html)
  • [FractionallySizedBox](https://api.flutter.dev/flutter/widgets/FractionallySizedBox-class.html)
  • [LayoutBuilder](https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html)
  • [MediaQuery](https://api.flutter.dev/flutter/widgets/MediaQuery-class.html)
  • [MediaQueryData](https://api.flutter.dev/flutter/widgets/MediaQueryData-class.html)
  • [OrientationBuilder](https://api.flutter.dev/flutter/widgets/OrientationBuilder-class.html)

Build Responsive UIs in Flutter


TDLR :

  • In responsive UI we don’t use hard-coded values for dimension and positions.
  • Use MediaQuery to get the real-time size of the window.
  • Use Flexible and Expanded widgets to get a flexible UI that works with percentage rather than hardcoded values.
  • Use LayoutBuilder to get the ConstraintBox of the parent widget.
  • You can get the orientation of the device using MediaQuery or OrientationBuilder.

  • 반응형 ui에서는 크기나 위치에 대한 하드 코딩된 값들을 사용하지 않는다.
  • window의 실시간 크기를 얻으려면 MediaQuery 를 사용하세요.
  • 하드 코딩된 값 대신 백분율을 사용하여 유연한 UI를 얻기 위해 Flexible and Expanded 위젯을 사용하세요.
  • 부모 위젯의 ConstraintBox 를 얻기 위해 LayoutBuilder 를 사용하세요.
  • 기기의 방향은 MediaQuery or OrientationBuilder 를 사용하여 얻을 수 있다.

What are the components of responsive design?

In responsive design apps, we have three major things to consider: size, orientation, and device type and whenever any of them changes, the app UI changes.

For example if you have a list of images in one column in portrait mode it should become two columns in landscape mode to show as much as possible to the user in one page and in this little example the UI depends on the orientation of the device in the next part we will discuss each component with examples.

반응형 디자인 앱에서, 우리가 고려해야 할 세 가지 주요 요소는 크기, 방향, 기기의 유형이며 이 중 하나라도 변경되면 앱의 UI가 변경된다.

예를 들어, 세로 모드에서 한 열의 이미지 목록이 있으면 가로 목록에서는 가능한 많은 콘텐츠를 한 페이지에서 사용자에게 표시하기 위해 두 열로 변경해야 한다. 이 작은 예에서 UI는 기기의 방향에 따라 달라진다. 다음 파트에서 각 구성 요소(크기, 방향, 기기 유형)에 대해 예제와 함께 스터디 해보자.

What’s the problem?

The main issue here is the hard-coded values for dimension and positions of your UI widgets. So to solve the problem just don’t use them, right? Yes but that’s just to solve one part of the problem because in responsive UI you don’t just scale Widgets, sometimes you re-position them and other times you change them according to the available space. In this article, I will give you some tips on how to do that.

INFO: The unit of measurement in flutter is logical pixels.

플러터에서 측정 단위는 논리적인 픽셀이다.

주된 문제는 ui 위젯의 크기와 위치에 대한 하드 코딩된 값이다. 이 문제를 해결하려면 그 값을 사용하지 않으면 된다! 그렇지 않은가? 하지만 그렇게 하면 그 문제의 일부만 해결하려고 하는 것이다. 반응형 UI에서는 위젯을 단순히 확대하는 것이 아니라 때로는 다시 배치하거나 공간에 따라 변경해야 한다.

1. Different screen sizes

반응형 1

Flutter support both android and IOS devices and both of them come in a wide variety of sizes it’s impossible to make a layout for each one of them but it’s possible and very easy to make your one layout scale to fit all of them and in Flutter we have a set of Widgets that help in this situation. let’s talk about some of them :

Flutter는 Aos와 Ios 기기를 모두 지원하고 이 두 플랫폼은 다양한 크기로 제공된다. 각각의 크기에 대한 레이아웃을 개별적으로 만드는 것은 불가능하지만 하나의 레이아웃을 만들고 모든 크기에 맞게 확장하는 것은 가능하며 이러한 상황을 돕는 위젯들이 있는데, 이 중 일부를 살펴보자!

The MediaQuery is an InhertedWidget that gives you information about the current media(AKA the windows that content your application) such as the size, orientation and Pixel Ration of the device.

So for example if you have a drawer menu and you want to show it only if the media width is less then 600 and if it’s greater then that you will show a normal menu in the left.

NOTE : 600 is just an example for an android tablet screen but if you want to know more about the right numbers you should read this for android and this for IOS

MediaQuery 는 현재 미디어(즉, 애플리케이션 콘텐츠를 포함하는 창)에 대한 정보를 제공하는 InhertedWidget 이다. 이 정보에는 기기의 크기, 방향 및 픽셀 비율과 같은 내용이 포함된다.

예를 들어 drawer 메뉴가 있고 너비가 600보다 작으면 드로어 메뉴를 표시하고 그 이상이면 왼쪽에 일반 메뉴를 표시하려면 다음과 같이 할 수 있다.

Widget build(BuildContext context) {
      
    media = MediaQuery.of(context).size;
      
    Scaffold(
        appBar: AppBar(),
        drawer: media.width < 600
            ? Drawer(
          child: Menu(),
        )
            : 
    ,
        body: Row(
          children: <Widget>[
            media.width > 600 ? Flexible(flex: 1, child: Menu()) : Container(),
            Flexible(
              flex: 3,
              child: Center(
                  child: Text(
                    "Size ${media.width} * ${media.height}",
                    style: Theme.of(context).textTheme.title,
                  )),
            ),
          ],
        ),
      );
    }

This example is very simple we have a Scaffold that contains a Row with two children a Text in the center and a menu in the left that will be shown only if the condition is true. the interesting the third line where I declared media

Now if you run this app in tablet and medium android device you will get different UIs :

이 예제는 매우 간단하다. Scaffold 가운데에 Text 위젯과 왼쪽에 메뉴가 있는 Row 가 포함되어 있고 조건이 참일 때만 메뉴가 나타난다. 흥미로운 부분은 세 번째 줄에서 media 를 선언한 부분이다.

이 앱을 태블릿과 중간 크기의 안드로이드 기기에서 실행되면 다음과 같이 다른 UI를 얻게 된다.

반응형 2 반응형 3

TIP: Use the breakpoint package to get useful information about the screen and break your screen layout into columns that you can easily hide/show depending on the window size

breakpoint 패키지를 사용하여 화면에 대한 유용한 정보를 얻고 창 크기따라 쉽게 숨기거나 표시할 수 있는 열로 화면의 레이아웃을 분할하세요.

As of now Android and IOS has real-time window change, for example, we have Multi-Window Support and in this mode, the size of the app can be modified by the user and using MediaQuery you can still get the exact size, let’s run the previous app in Multi-Window mode and as you can see it works as expected.

현재 Aos와 iOS의 실시간 창 변경 기능을 제공한다. 예를 들어, Multi-Window 와 같은 모드에서는 앱의 크기를 사용자가 조정할 수 있고 MediaQuery 를 사용하여 정확한 크기를 얻을 수 있다. Multi-Window mode 에서 이전 예제를 실행한 것인데 예상대로 작동하는 것을 확인할 수 있다.

이전 예제에서는 유연한 디자인을 얻기 위해 MediaQuery 를 사용했지만 Flexible 과 같은 다른 위젯도 사용했다. 이러한 위젯은 FlexBox 레이아웃 시스템을 따른다. 이에 대해 조금 더 알아보자!

Flexible and Expanded are two widgets that you can use inside a RowColumn, or Flex to give their children the flexibility to expand to fill the available space and the main difference between them can be shown in this example :

Flexible and ExpandedRowColumn, or Flex 위젯 내에서 사용하여 자식에게 남은 공간을 사용할 수 있도록 하는 유연성을 가진 두 가지 위젯이다. 이들의 주요 차이점을 다음 예제에서 볼 수 있다.

반응형 4

Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Row(
            children: <Widget>[
              buildExpanded(),
              buildFlexible(),
            ],
          ),
          Row(
            children: <Widget>[
              buildExpanded(),
              buildExpanded(),
            ],
          ),
          Row(
            children: <Widget>[
              buildFlexible(),
              buildFlexible(),
            ],
          ),
        ],
      ),
    );

buildFlexible and buildExpanded are just two functions they return the right widget.

For example :

Widget buildFlexible() {
      
    Flexible(
        child: Container(
          color: Colors.green,
          child: Text(
            "Flexible",
            style: Theme.of(context).textTheme.display1,
          ),
        ),
      );
    }

NOTE: If you don’t provide a flex value the default value is 1

flex 값을 제공하지 않으면 기본값은 1이다!

So the difference is that the Expanded widget requires the child to fill the available space while Flexible does not. and now you can use them to distribute space between multiple items

따라서 차이점은 Expanded 위젯은 자식이 사용 가능한 공간을 채우도록 요구하는 반면 Flexible 은 그렇지 않다는 것이다! 이것들을 사용해서 여러 항목 간에 공간을 분배할 수 있다.

return new Column(
  children: <Widget>[
    new Expanded(
      flex: 2,
      child: new Container(
        color: Colors.red,
      ),
    ),
    new Expanded(
      flex: 8,
      child: new Container(//use your Gridview instead 
        color: Colors.green,
      )
    )
  ],

);

반응형 6

The MediaQuery widget will give you the global size available for your application meanwhile you can think of LayoutBuilder as a local MediaQuerybut more focus on the size constraints so it will provide you with the parent widget’s constraints to read them and decide what to display according to them

MediaQuery 위젯은 애플리케이션에 사용 가능한 전역 크기를 제공하지만, LayoutBuilder 위젯을 로컬 MediaQuery 와 유사하게 생각할 수 있고 크기 제약 사항에 중점을 두어 부모 위젯의 제약 사항을 제공하여 그에 따라 표시할 내용을 결정한다.

댓글남기기