Tempo Di Valse

[Flutter/적응기] Multi-platform 개발 접근하기 (Desktop/Mobile) 본문

개발/Flutter

[Flutter/적응기] Multi-platform 개발 접근하기 (Desktop/Mobile)

TempoDiValse 2022. 2. 9. 11:55

Flutter 가 2.10 부터는 Windows 개발까지 지원한다고 하여 One Source Multi-platform 개발의 최종 보스가 될 것 같은 예감에 공부를 시작해보기로 했다.

 

맨 먼저 하나의 프로젝트에서 쉽게 각 플랫폼에 맞도록 UI 화면을 달리 보여주는 작업을 하는 것을 해봤다.

 

기본 IDE 는 Android 개발자이기 때문에 접근하기에 쉬운 Android Studio 로 시작하였으며, Flutter 공식 홈페이지의 가이드를 통해서 Android Studio 를 통해서 개발 할 수 있도록 셋팅을 다 마친 상태이다.

 

Android Studio 를 통해서 'New Flutter Project' 를 하게되면,

하단에 어떤 플랫폼을 함께 개발할 것인지 선택할 수 있도록 해준다. 이 후에 프로젝트를 만들게 되면 각 플랫폼 별로 Flutter 가 알아서 컴파일 할 수 있도록 서브 프로젝트 폴더를 만들어준다.

- android : Android 기본 프로젝트 폴더. app 단위의 build.gradle 을 보게 되면, Flutter 와 연동 할 수 있도록 gradle 이 바뀌어져 있다.

 

- ios : iOS 기본 프로젝트 폴더, Runner 폴더 내에 AppDelegate.swift 을 보게 되면, UIIApplicationMain Annotation 이 일반 App가 Flutter 와 연동 될 수 있도록 UIResponder, UIApplicationDelegate 이 아닌 FlutterAppDelegate 로 되어있다.

 

- macos : OS X 기본 프로젝트 폴더. iOS 폴더랑 비슷하다.

- windows : Windows 기본 프로젝트 폴더, C++ 로 되어있다. (큰일났다)

- web : 홈페이지 기본 프로젝트 폴더

- lib : 실제 Flutter 를 구현하는 dart 폴더

 

 

Windows 까지도 개발하기 위해서 Flutter 에 손을 댔지만 개발 환경은 맥북을 쓰고 있기 때문에 MacOS 와 Android 가 잘 돌아가는 지 확인을 하려고 한다.

 

일단 프로젝트를 생성할 때 만들어지는 기본 파일을 삭제 한 후, 깨끗한 dart 파일을 만들었다.

// app.dart

import 'package:flutter/material.dart';

void main(){
  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "App",
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.blue,
      ),

      home: main,
    );
  }
}
이건 선택사항인데, 첫 시작 파일이 main.dart 가 아닌 다른 dart 파일인 경우에는 'Run' 하게 되면 'Edit Configuration' 화면이 뜨게 되는데, 이는 main.dart 를 찾을 수 없어서 나타나는 현상이기 때문에 main.dart 가 써있는 부분을 사용하고자 하는 파일로 변경해주면 된다.

다음으로 데스크탑의 UI 와 모바일의 UI 를 다르게 보이기 위해서 폴더 구조를 조금 나눠보았다. 해당 예시는 편의상 알아보기 쉽도록 했기 때문에 본인이 편한대로 만들면 되겠다.

나 같은 경우에는,

 

- ui/desktop/main.dart

- ui/mobile/main.dart

 

이렇게 두 파일을 통해서 각각 뿌려주도록 만들었다.

 

각 파일 코딩 내용은 별건 없다.

// ui/desktop/main.dart

import 'package:flutter/material.dart';

import 'package:test_app/util/logger.dart';

class Main extends StatelessWidget {
  const Main({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;

    Log.p("App", "Size: ${size.width.toInt()} / ${size.height.toInt()}");

    return Container(
      child: const Text(
        'Test Desktop Application',
        style: TextStyle(
          color: Colors.black,
          fontSize: 24,
        ),
      ),
      color: Colors.white,
    );
  }
}
// ui/mobile/main.dart

import 'package:flutter/material.dart';

import 'package:test_app/util/logger.dart';

class Main extends StatelessWidget {
  const Main({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;

    Log.p("App", "Size: ${size.width.toInt()} / ${size.height.toInt()}");

    return Container(
      child: const Text(
        'Test Mobile Application',
        style: TextStyle(
          color: Colors.black,
          fontSize: 24,
          fontFamily: 'Roboto',
        ),
      ),
      color: Colors.white,
    );
  }
}

이렇게 간단하게 분기되었는 지만 알 수 있도록 만들어주고, 처음 구동하는 dart 파일을 손보도록 한다.

 

// app.dart

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

import 'package:test_app/ui/desktop/main.dart' as desktop;
import 'package:test_app/ui/mobile/main.dart' as mobile;

void main(){
  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    StatelessWidget? main;

    switch(Theme.of(context).platform){
      case TargetPlatform.android:
      case TargetPlatform.iOS:
        main = const mobile.Main();
        break;
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
        main = const desktop.Main();
        break;
      default: main = null; break;
    }

    return MaterialApp(
      title: "App",
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.brown,
      ),

      home: main,
    );
  }
}

 

 

해당 위치에서 실행되는 플랫폼이 어느 곳 인지 확인하기 위해서는 context 가 있는 지점에서 파악이 가능하기 때문에 Widget 단위 클래스의 build 메소드 내에서 감지를 해야 한다. 그래서 platform 정보를 가져올 수 있는 Theme.of() 메소드를 이용하여 TargetPlatform 데이터와 각각 비교를 한다.

 

android/ios 는 mobile 폴더에 있는 Main 을, OS X/Windows 는 desktop 폴더에 있는 Main 을 바라볼 수 있도록 하고 Device 를 선택하여 Run 해보면,

 

맥북에서 돌려본 결과이다.
이건 안드로이드에서 돌려본 결과

 

일단 플랫폼 별로 분기처리 할 수 있는 로직을 확인했으니, 다음에는 태블릿과 폰의 회전을 분기할 수 있는 로직을 알아봐야겠다.

반응형

'개발 > Flutter' 카테고리의 다른 글

[Flutter/적응기] OS에 따른 Dialog 를 뿌려주기  (0) 2022.03.02
Comments