내가 만들고 있는 앱에서 ModalBottomSheet를 사용하는데 안드로이드 애뮬레이터에서는 네비게이션 모드(제스처 바 or 3버튼)에 따라 ModalBottomSheet의 위치가 애매하게 렌더링 된다.
이 부분을 개선하기 위해 작성한 코드를 공유해본다.
/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"
}
}
}
/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';
}
}
위에서 작성한 코드로 가져올 안드로이드 네비게이션 모드 정보를 활용할 위젯 등 본인의 코드로 가서 아래의 코드를 참고하여 적용하면 된다.
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,
),
.
.
.
),
);
}
}
안드로이드 애뮬레이터로 돌렸을 때 아래와 같이 네비게이션 모드가 3버튼이면 Modal의 위치가 좀 더 올라가게 된다. 내가 원했던 결과 그대로 얻을 수 있었다.
왜 기업에서 Flutter 개발자를 고용할 때 네이티브 앱 개발 경력을 보는지 Flutter로 앱을 개발하면서 실감하고 있다.
앞으로 계속 Flutter로 앱을 개발하면서 네이티브 코드를 다뤄야 할 경우가 많이 생길 것 같다는 느낌이 강하게 온다.
그리고 이 포스트의 주제와는 맞지 않지만, 안드로이드가 너무 싫다!!! 왠진 모르겠지만 ios 애뮬레이터에서는 멀쩡하게 잘 돌아가는 코드가 안드로이드 애뮬레이터로 돌리기만 하면 위젯이 제대로 렌더링되지 않는다던지 등 문제가 너무 많아서 요즘은 안드로이드 애뮬레이터를 메인으로 디버깅하고 있다. (아직 flutter 초보이고 실제 기기로 돌려보면 또 다를 수도 있겠지만...)
뭐 아무튼, 제가 작성한 코드에 개선할 점이 있다면 어떤 피드백이든 좋으니 댓글 남겨주세용~