[Flutter] 안드로이드 네비게이션 모드 가져오기

Hyunzai·2025년 5월 17일

Flutter

목록 보기
3/4
post-thumbnail

내가 만들고 있는 앱에서 ModalBottomSheet를 사용하는데 안드로이드 애뮬레이터에서는 네비게이션 모드(제스처 바 or 3버튼)에 따라 ModalBottomSheet의 위치가 애매하게 렌더링 된다.

이 부분을 개선하기 위해 작성한 코드를 공유해본다.


1. Android Native Code

/android/app/src/main/kotlin/당신의/패키지/네임/MainActivity.kt 해당 경로의 코드를 아래와 같이 수정

package com.example.yourAppName //본인의 앱 패키지명

import android.os.Build
import android.provider.Settings
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "android_navigation_mode_detector"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
            call, result ->
            if (call.method == "getNavigationMode") {
                result.success(getNavigationMode())
            } else {
                result.notImplemented()
            }
        }
    }

    private fun getNavigationMode(): String {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10 이상부터 navigation_mode 설정값이 존재함
            try {
                val mode = Settings.Secure.getInt(contentResolver, "navigation_mode")
                when (mode) {
                    2 -> "gesture" // Fully gesture
                    1 -> "2button" // 2-button (Android 9 스타일)
                    0 -> "buttons" // 3-button
                    else -> "unknown"
                }
            } catch (e: Settings.SettingNotFoundException) {
                "unknown"
            }
        } else {
            "buttons"
        }
    }
}

2. Flutter(Dart) Code

/lib 아래에 새로운 파일을 생성하고 아래와 같이 작성
나는 파일명을 android_navigation_mode_detector.dart 로 했다.

import 'dart:developer';

import 'package:flutter/services.dart';

class AndroidNavigationModeDetector {
  static const MethodChannel _channel = MethodChannel(
    'android_navigation_mode_detector',
  );

  static Future<String> getNavigationMode() async {
    try {
      final String result = await _channel.invokeMethod('getNavigationMode');
      return result;
    } on PlatformException catch (e) {
      log("NavigationModeDetector error: ${e.message}");
      return 'unknown';
    }
  }

  static Future<bool> isGestureNavigation() async {
    return (await getNavigationMode()) == 'gesture';
  }

  static Future<bool> isButtonNavigation() async {
    return (await getNavigationMode()) == 'buttons';
  }
}

3. 코드 적용

위에서 작성한 코드로 가져올 안드로이드 네비게이션 모드 정보를 활용할 위젯 등 본인의 코드로 가서 아래의 코드를 참고하여 적용하면 된다.

import 'package:flutter/material.dart';
import 'package:yourAppName/android_navigation_mode_detector.dart'; //yoarAppName은 본인 앱이름
import 'dart:io' show Platform; // IOS, Android 구분용

class YourWidget extends StatefulWidget {
  const YourWidget({super.key});

  
  State<YourWidgetWidget> createState() => _YourWidgetState();
}

class _YourWidgetState extends State<YourWidget> {
  String _mode = ''; //받아온 mode string을 담을 변수

  
  void initState() {
    super.initState();
    
    // 앱이 구동되고 있는 디바이스가 Android라면 Platform.isAndroid => true
    if (Platform.isAndroid) _loadNavigationMode();
  }

  //네비게이션 모드 문자열을 가져오는 메서드
  Future<void> _loadNavigationMode() async {
    final mode = await AndroidNavigationModeDetector.getNavigationMode();
    setState(() {
      _mode = mode;
    });
  }

  
  Widget build(BuildContext context) {
    return SizedBox(
      height: MediaQuery.of(context).size.height * 0.35,
      width: MediaQuery.of(context).size.width,
      child: Container(
        margin: EdgeInsets.only(
          left: 25,
          right: 25,
          // 나는 디바이스가 ios이거나, _mode가 gesture라면 모달의 아래 여백을 25로, 
          // 아니라면(안드로이드이면서 네비게이션 모드가 '3버튼'일경우) 55를 설정하도록 했다.
          bottom: Platform.isIOS || _mode == "gesture" ? 25 : 55,
        ),
        .
        .
        .
      ),
    );
  }
}

4. 결과

안드로이드 애뮬레이터로 돌렸을 때 아래와 같이 네비게이션 모드가 3버튼이면 Modal의 위치가 좀 더 올라가게 된다. 내가 원했던 결과 그대로 얻을 수 있었다.


5. 마무리

왜 기업에서 Flutter 개발자를 고용할 때 네이티브 앱 개발 경력을 보는지 Flutter로 앱을 개발하면서 실감하고 있다.
앞으로 계속 Flutter로 앱을 개발하면서 네이티브 코드를 다뤄야 할 경우가 많이 생길 것 같다는 느낌이 강하게 온다.

그리고 이 포스트의 주제와는 맞지 않지만, 안드로이드가 너무 싫다!!! 왠진 모르겠지만 ios 애뮬레이터에서는 멀쩡하게 잘 돌아가는 코드가 안드로이드 애뮬레이터로 돌리기만 하면 위젯이 제대로 렌더링되지 않는다던지 등 문제가 너무 많아서 요즘은 안드로이드 애뮬레이터를 메인으로 디버깅하고 있다. (아직 flutter 초보이고 실제 기기로 돌려보면 또 다를 수도 있겠지만...)




뭐 아무튼, 제가 작성한 코드에 개선할 점이 있다면 어떤 피드백이든 좋으니 댓글 남겨주세용~

profile
개발블로그

0개의 댓글