[Flutter] MaterialStateProperty 너는 무엇이냐

Flutter를 사용하면서 항상 헷갈렸던 MaterialStateProperty가 무엇인지에 대해 알아보자
Minha Sohn's avatar
Apr 05, 2024
[Flutter] MaterialStateProperty 너는 무엇이냐
목차
 

MaterialStateProperty 너는 무엇이냐.

Flutter 개발을 시작하고 종종 마주하는 이 클래스… MaterialStateProperty.
이 클래스로 색깔이나 사이즈 등 거의 모든걸 정의할 수 있는 것 처럼 보였다. 근데 flutter를 조금 써봤다면 알다시피 쉽게 클래스의 프로퍼티를 가져다 색이나 사이즈를 지정할 수 있다.
const DropdownMenu({ super.key, this.enabled = true, this.width, this.label, this.hintText, this.helperText, this.errorText, });
 

그래서 flutter는 왜 굳이 MaterialStateProperty 를 새로 만든걸까?

사실 위의 예시 코드인 DropdownMenu는 훨씬 더 많은 수의 프로퍼티를 가지고 있다.
자세히 살펴보면 Text에도 hintText, ErrorText, helperText 등 같은 텍스트여도 상황에 맞는 프로퍼티를 따로 클래스에 따로 정의해 둔 것을 알 수 있다.
const DropdownMenu({ super.key, this.enabled = true, this.width, this.menuHeight, this.leadingIcon, this.trailingIcon, this.label, this.hintText, this.helperText, this.errorText, this.selectedTrailingIcon, this.enableFilter = false, this.enableSearch = true, this.textStyle, this.inputDecorationTheme, this.menuStyle, this.controller, this.initialSelection, this.onSelected, this.requestFocusOnTap, this.expandedInsets, this.searchCallback, required this.dropdownMenuEntries, });
 
그래서 구글은 생각한 것이다.
새로운 기능이 추가될 때 마다 이렇게 클래스에 프로퍼티를 추가할 것인가? 어짜피 이미 10개가 넘는 프로퍼티가 있는데 조금 더 추가 된다고 문제 될 게 있을까?
 
여기서 구글은 프로퍼티를 매번 프로퍼티를 추가하기 보다는 프로퍼티를 지워가는 방향으로 접근 했다. 이는 아래의 문장을 읽어보면 무슨 말인지 이해할 수 있다.
 
The solution the Material team came up with was no longer accept a static value for something like background color, but instead to accept a function that returns a color.
 
예를 들어, 앞으로는 단순히 background color 처럼 프로퍼티를 추가하는 것이 아니라 원하는 색을 리턴하는 함수를 추가하겠다는 말이다.
 
MaterialState는 flutter의 여러 state를 가지고 있다. 이렇게 여러 상태를 한번에 원하는대로 상황에 맞게 색이나 사이즈등을 지정할 수 있다. 또는 특정 상태만 되도록 조건을 만들 수도 있다.
Color getColor(Set<MaterialState> states) { const Set<MaterialState> interactiveStates = <MaterialState>{ MaterialState.pressed, MaterialState.hovered, MaterialState.focused, }; // pressed, hovered, focused 된 상태라면 파란색 if (states.any(interactiveStates.contains)) { return Colors.blue; } // 아니라면 빨간색 return Colors.red; }
// 또는 if (states.contains(MaterialState.focused) && states.contains(MaterialState.hovered) { return Colors.blue; }
 
아래의 코드는 위의 예시코드의 전문이다.
실제 색을 지정하는 로직에서는 getColor를 호출하면서 코드를 가독성있게 정리 할 수도 있다.
import 'package:flutter/material.dart'; /// Flutter code sample for [MaterialStateProperty]. void main() => runApp(const MaterialStatePropertyExampleApp()); class MaterialStatePropertyExampleApp extends StatelessWidget { const MaterialStatePropertyExampleApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('MaterialStateProperty Sample')), body: const Center( child: MaterialStatePropertyExample(), ), ), ); } } class MaterialStatePropertyExample extends StatelessWidget { const MaterialStatePropertyExample({super.key}); @override Widget build(BuildContext context) { Color getColor(Set<MaterialState> states) { const Set<MaterialState> interactiveStates = <MaterialState>{ MaterialState.pressed, MaterialState.hovered, MaterialState.focused, }; if (states.any(interactiveStates.contains)) { return Colors.blue; } return Colors.red; } return TextButton( style: ButtonStyle( // 함수 호출 foregroundColor: MaterialStateProperty.resolveWith(getColor), ), onPressed: () {}, child: const Text('TextButton'), ); } }
background color를 사용해 색을 지정할 때 보다 코드가 길어진 것은 사실이나 좀 더 자유도 있고, 개발자의 의도대로 코드를 작성할 수 있다는 것은 큰 장점인 것 같다.
또한 영상에서 설명하듯 프로퍼티를 더 이상 늘이지 않고 줄이는 방향으로 개발을 진행한다고 했기에, 정말 나중에 저렇게 많은 클래스의 프로퍼티들이 없어지게 되지 않을까? 라는 생각도 해본다.
 

글을 마치며…

Reference에 태그한 영상으로 미루어보아 MaterialStateProperty 클래스는 Material3를 적용되면서 사용된 것으로 보인다. (약 1년전)
아직 background Color 처럼 정적으로 프로퍼티를 사용하는 방법과 MaterialStateProperty 를 사용하는 두가지 방법이 혼재되고 있어 나같은 뉴비(?)는 처음에 많이 헷갈렸다…
하지만 이제는 이러한 배경의도를 알게 되었으니 적재적소에 MaterialStateProperty 와 정적인 방법 두가지를 사용할 수 있을 것 같다.
 

References

Share article

haccoon