flutter 2.0 부터 새로운 버튼 테마들과 함께 스타일 선언방식이 바뀌었다.
요약하자면,
- 고정된 Material Design variation사용할 때
styleFrom
TextButton( style: TextButton.styleFrom( primary: Colors.blue, onSurface: Colors.red, ), ... )
- 유동적으로 버튼의 상태 또는 특정 조건에 의해 스타일이 달라질 땐
TextButton( style: ButtonStyle( overlayColor: MaterialStateProperty.resolveWith<Color>( (Set<MaterialState> states) { if (states.contains(MaterialState.focused)) return Colors.red; if (states.contains(MaterialState.hovered)) return Colors.green; if (states.contains(MaterialState.pressed)) return Colors.blue; return null; // Defer to the widget's default. }), ), ... )
component/button.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/screen_util.dart';
import '../../../themes/candy_theme.dart';
import '../../../themes/color_styles.dart';
class CandyButtonStyle {
CandyButtonStyle._();
static ButtonStyle get containedButton => ElevatedButton.styleFrom(
primary: CandyColors.candyBlue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2.0),
),
textStyle: CandyTheme.textTheme.headline6,
minimumSize: Size.fromHeight(
ScreenUtil().setHeight(56.0),
),
);
static ButtonStyle get containedButton48 => containedButton.copyWith(
minimumSize: MaterialStateProperty.all(
Size.fromHeight(
ScreenUtil().setHeight(48.0),
),
),
textStyle: MaterialStateProperty.all(
CandyTheme.textTheme.subtitle2,
),
);
static ButtonStyle get containedButton32 => containedButton.copyWith(
minimumSize: MaterialStateProperty.all(
Size.fromHeight(
ScreenUtil().setHeight(32.0),
),
),
textStyle: MaterialStateProperty.all(
CandyTheme.textTheme.subtitle2,
),
);
...
선언 코드
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('contained button'),
style: CandyButtonStyle.containedButton,
onPressed: () {},
),
),
Expanded(
child: TextButton(
child: const Text('contained disabled button'),
style: CandyButtonStyle.containedButton,
onPressed: null,
),
),
],
),
Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('contained button'),
style: CandyButtonStyle.containedButton,
onPressed: () {},
),
),
Expanded(
child: TextButton(
child: const Text('contained disabled button'),
style: CandyButtonStyle.containedButton,
onPressed: null,
),
),
],
),
...
높이 설정 이슈 발생..ㅠ
선언해둔 위 버튼은 크기를 스타일 설정하는 속성은 minimumSize
뿐이고, 말그대로 minimumSize이기에 해당 위젯의 스타일(예를 들어 텍스트 크기라던지 등) 작을 때만 minimumSize
가 유의미하게 쓰일 뿐! 설정해둔 사이즈보다 작을 땐 작은 사이즈가 설정된 것!!
cf.
setting minimumSize height 20
- A button: height 43 -> 20 ⭕️
- B button: height 74 -> 20 ⭕️
- C button: height 14 -> 14 ❌ (minimum size 설정 안됨)
ConstrainedBox
제약조건 설정 박스로 위젯을 감싸준다.ConstrainedBox(
constraints: const BoxConstraints.tightFor(height: 48),
child: Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('contained button2'),
style: CandyButtonStyle.containedButton48,
onPressed: () {},
),
),
Expanded(
child: TextButton(
child: const Text('contained disabled button2'),
style: CandyButtonStyle.containedButton48,
onPressed: null,
),
),
],
),
),
or
Container(
height: 48,
width: double.maxFinite,
child: ElevatedButton(
child: const Text('contained large'),
style: CandyButtonStyle.containedButtonLarge,
onPressed: () {},
),
)
or
Container(
height: 48,
width: double.maxFinite,
child: Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('contained large'),
style: CandyButtonStyle.containedButtonLarge,
onPressed: () {},
),
),
Expanded(
child: TextButton(
child: const Text('contained large'),
style: CandyButtonStyle.containedButtonLarge,
onPressed: null,
),
),
],
),
)