이번시간부터 가장 많이 사용 되는 5가지 위젯 Text, Row, Column, Stack Container를 하나씩 차례로 살펴볼건데요. Flutter 공식페이지에 있는 매뉴얼을 번역한 자료를 가지고 볼거에요. 매뉴얼은 읽기에 매우 지루합니다. 하지만 일단 이 5가지 위젯에 대한 매뉴얼에 익숙해 지신다면 다른 위젯들을 다룰때 매뉴얼을 찾아보기가 아주 쉬워지실겁니다. 지루하더라도 하나씩 꼼꼼히 보시고 매뉴얼의 패턴을 익혀주시기 바래요.
이하 본문은 Flutter의 매뉴얼 Text class를 번역하여 작성한 블로그입니다:
원문: https://api.flutter.dev/flutter/widgets/Text-class.html
Text 위젯은 하나의 문자열을 표현하기 위해 사용되고 해당 문자열에 스타일도 가미할수 있습니다. style속성은 반드시 기재해야하는 항목은 아니기 때문에 생략했을때는 가장 근접하게 설정된 DefaultTextStyle을 선택해서 스타일로 적용합니다.
맛보기 코드 #1
아래 코드는 문자열이 정해진 구역을 넘어갈때 어떻게 처리할지를 보여줍니다.
Text(
'Hello Ruth, How are you?',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.bold),
)
Text.overflow속성이 TextOverflow.ellipsis로 설정되어 있기때문에 문자열이 길어지면 뒷쪽 구간은 생략기호(…)으로 표시가 됩니다.
맛보기 코드 #2
Text.rich()를 이용하면 하나의 Text안에서 더욱 다양한 스타일의 문자표현을 할수 있습니다. 아래 코드는 Text.rich() 아래 TextSpan을 넣어서 다양한 스타일을 구성한 문자열을 보여줍니다.
const Text.rich(
TextSpan(
text: 'Hello', // default text style
children: <TextSpan>[
TextSpan(text: ' beautiful ', style: TextStyle(fontStyle: FontStyle.italic)),
TextSpan(text: 'world', style: TextStyle(fontWeight: FontWeight.bold)),
],
),
)
Text.rich안쪽에 TextSpan을 넣고 그 밑에 text와 style을 정의함으로써 문자열을 꾸미는데요. TextSpan에는 children속성이 있어서 배열로 여러개의 TextSpan을 넣어서 다양하게 스타일링 할수도 있습니다.
상호작용 (Interactivity)
Text위젯을 버튼처럼 누르게 만들고 싶다면 GestureDetector위젯으로 싸서 만들수 있긴 하지만 그닥 추천하는 바는 아닙니다. Text로 만들어진 문자열을 클릭하도록 만들고 싶으시면 TextButton 위젯을 쓰시기를 추천드립니다. TextButton을 사용할수 없는 환경이라면 적어도 InkWell을 사용하시기를 권장드립니다.
선택기능 (Selection)
Text는 기본적으로 선택을 할수 없게 만들어져 있습니다. 그럼에도 불구하고 Text상자를 선택하고자 하실때는 SelectionArea위젯으로 감싸면 이하 서브트리의 위젯들은 선택을 할수 있게 됩니다. 그리고 반대로 해당 서브트리 안에서 특정 위젯들만 선택을 하지 못하게 설정하고 싶을때는 필요한 위젯만 SelectionContainer.disabled로 감싸면 됩니다. 아래 예제를 보면서 더욱 자세히 설명드리도록 하겠습니다. 터미널을 열고 flutter create --sample=widgets.Text.3 mysample 명령어를 실행하시면 Flutter에서 제공하는 예제가 mysample 폴더안에 자동으로 생성됩니다. 생성된 mysample의 main.dart는 다음과 같습니다.
import 'package:flutter/material.dart';
void main() => runApp(const SelectionContainerDisabledExampleApp());
class SelectionContainerDisabledExampleApp extends StatelessWidget {
const SelectionContainerDisabledExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('SelectionContainer.disabled Sample')),
body: const Center(
child: SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Selectable text'),
SelectionContainer.disabled(child: Text('Non-selectable text')),
Text('Selectable text'),
],
),
),
),
),
);
}
}
지난 시간에 배웠던 StatelessWidget이 이제 눈에 확들어오시죠? SelectionContainerDisabledExampleApp로 StatelessWidget로 정의하고 runApp에서 호출하도록 구성이 되어있습니다. 코드를 보시면요 build함수에 위젯트리가 머리속에 그려지시나요? MaterialApp이 위젯트리의 최상단에 위치하고 그 밑에 Scaffold가 위치하고 그 밑에 appBar와 body가 나란히 내려오는데 여기서 body를 보시면 Center위젯으로 감싸져있는데 child에 SelectionArea로 감싸줘서 이하 위젯트리들은 선택할수 있도록 만들었습니다. 그래서 Column의 children 중 하나인 Text, “Selectable text”는 선택이 가능하게 되고, 그 밑에 SelectionContainer.disabled로 추가로 감싸진 Text, “Non-selectable text”는 선택이 안되게 됩니다. 그 뒤에 Text도 SelectionContainer.disabled로 감싸주지 않았기 때문에 위젯트리에 입각해서 SelectionArea의 영향을 받아 선택할수 있게 됩니다. 만약 여기서 SelectionArea 바깥에 Text를 하나 넣었다면 Text는 기본적으로 선택이 안되기 때문에 선택할수 없는 문자열이 되겠죠?
그 밖에도:
- RichText로 Text보다 더 현란한 스타일을 표현할수 있고요
- DefaultTextStyle로는 Text위젯의 기본 스타일을 정의 할수 있습니다.
- SelectableRegion은 SelectionArea와 마찬가지로 그 안에 있는 위젯들을 선택할수 있게 바꿔주는데 SelectionArea가 Material library의 설정의 따른다면 SelectableRegion은 플랫폼에 연계된 설정이기 때문에 코드에서는 SelectableRegion보다는 SelectionArea가 사용이 용이합니다.
상속 계보도 (Inheritance)
Text가 상속받는 클래스의 계보도는 다음과 같습니다.
Object > DiagnosticableTree > Widget > StatelessWidget > Text
생성자 (Constructors)
Text(String data, {Key? key, TextStyle? style, StrutStyle? strutStyle, TextAlign? textAlign, TextDirection? textDirection, Locale? locale, bool? softWrap, TextOverflow? overflow, @Deprecated(‘Use textScaler instead. ‘ ‘Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ‘ ‘This feature was deprecated after v3.12.0-2.0.pre.’) double? textScaleFactor, TextScaler? textScaler, int? maxLines, String? semanticsLabel, TextWidthBasis? textWidthBasis, TextHeightBehavior? textHeightBehavior, Color? selectionColor})Creates a text widget.const
Text.rich(InlineSpan textSpan, {Key? key, TextStyle? style, StrutStyle? strutStyle, TextAlign? textAlign, TextDirection? textDirection, Locale? locale, bool? softWrap, TextOverflow? overflow, @Deprecated(‘Use textScaler instead. ‘ ‘Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ‘ ‘This feature was deprecated after v3.12.0-2.0.pre.’) double? textScaleFactor, TextScaler? textScaler, int? maxLines, String? semanticsLabel, TextWidthBasis? textWidthBasis, TextHeightBehavior? textHeightBehavior, Color? selectionColor})Creates a text widget with a InlineSpan.const
속성 (Properties)
data → String? 화면에 보여줄 문자열final
hashCode → int 객체의 해쉬코드read-only inherited
key → Key? 위젯트리에서 서로 자리를 옮기거나 할때 필요한 키값final inherited
locale → Locale? 사용자의 지역에 따라서 유니코드가 다르게 랜더링될때 필요에 따라 적절한 폰트를 선택하는데 사용final
maxLines → int? 문자열이 많은 경우 줄바꿈을 하여 보여주다가 줄바꿈 한 라인이 여기서 정한 최대값을 넘어서면 overflow에 정의한대로 행동final
overflow → TextOverflow? 문자열이 많아서 지정한 구역을 넘어갈때 어떻게 대처할지는 정하는 곳final
runtimeType → Type 객체의 런타임 유형read-only inherited
selectionColor → Color? 문자열을 선택했을때 보여줄 배경색상final
semanticsLabel → String? data로 넣은 문자열이 무엇을 의미하는지 설명해 놓는곳final
softWrap → bool? 문자열의 Wrap방법을 soft로 할지 정하는 곳. softWrap을 true로 설정하면 해당 문자열이 하나의 문단으로 취급되어 단락이 나뉘지 않는다.final
strutStyle → StrutStyle? 입력된 텍스트의 높이가 할당된 공간에 맞도록 하고자 할때
style → TextStyle? 문자열을 꾸며줄 스타일을 정의하는 곳final
textAlign → TextAlign? 수평정렬final
textDirection → TextDirection? 문자열의 방향final
textHeightBehavior → TextHeightBehavior? 문자열의 위나 아래에 TextStyle.height을 어떻게 설정할지 결정final
textScaleFactor → double?이 속성은 더이상 지원하지 않습니다. 기능은 textScaler로 대체할수 있습니다.
textScaler → TextScaler? 문자열을 배치하고 렌더링할때 사용할 폰트크기를 조정final
textSpan → InlineSpan? 문자열을 InlineSpan으로 보여주고자 할때 사용final
textWidthBasis → TextWidthBasis? 문자열의 가로너비를 측정하는 방법을 정의final
클래스 내부함수 (Methods)
build(BuildContext context) → Widget
위젯들을 정의하여 화면을 구성하는 실제 UI를 구성하는데 사용override
createElement() → StatelessElement
위젯트리에서 해당 위젯의 위치를 관리하기 위해 StatelessElement를 생성inherited
debugDescribeChildren() → List<DiagnosticsNode>
이 노드의 하위 항목을 설명하는 DiagnosticsNode객체 목록을 반환inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
노드와 관련된 추가 속성을 정의override
noSuchMethod(Invocation invocation) → dynamic
존재하지 않는 메서드나 속성에 액세스할 때 호출inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
디버깅 도구 및 DiagnosticsNode.toStringDeep에서 사용되는 개체의 디버그 표현을 반환inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
이 개체를 문자열로 표현하여 반환inherited
toStringDeep({String prefixLineOne = ”, String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
이 노드와 그 하위 항목의 문자열 표현을 반환inherited
toStringShallow({String joiner = ‘, ‘, DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
객체에 대한 한 줄의 자세한 설명을 반환inherited
toStringShort() → String
이 위젯에 대한 간단한 텍스트 설명inherited
연산자 (Operators)
operator ==(Object other) → bool
동일함을 비교하는 연산자inherited
여기까지 Flutter공식페이지에서 제공하는 Text class에 대한 매뉴얼이었습니다. 반드시 원문 페이지에 들어가서 다시 한번 살펴보시기를 권장드리고 해당 페이지에서 설명이 충분하지 않은 부분은 링크를 클릭해서 직접 들어가 보시기 바랍니다. 그런 소소한 습관들이 나중에 필요한 정보를 습득하는데 큰 도움이 될거에요. 지루하셨을텐데 잘 따라와 주셔서 감사합니다. 우리는 다음시간에 Row class로 다시 만나요. 감사합니다.