반응형
해당 포스팅의 전체 소스 코드가 포함된 프로젝트 파일은 깃허브에서 다운로드 가능합니다.
https://github.com/luvris2/flutter-example/tree/main/flutter_widget_test
Scaffold 위젯
- MaterialApp의 디자인 레이아웃을 제공하는 위젯
- 일반적으로 사용되는 많은 UI 구성 요소를 포함하는 컨테이너
- 앱 바, 플로팅 작업 버튼, 하단 내비게이션 바 등
- 즉, 개발자가 UI 구성 요소를 추가 또는 제거하고 모양을 변경하거나 기능을 추가하는 작업을 할 수 있음
- 하위 위젯
- appBar
- 화면 상단에 앱 바를 표시하는 하위 위젯
- 일반적으로 제목과 선택적으로 일부 작업 또는 탐색 버튼을 포함 (글쓰기 버튼 등)
- body
- appBar 아래에 나타나는 화면의 메인 콘텐츠를 표시하는 위젯
- 포시되는 위젯 : Text위젯, ListView위젯, Column&Row 위젯 등
- floatingActionButton
- 화면 우측 하단에 플로팅 액션 버튼을 표시하는 서브 위젯
- 새 항목 추가, 새 작업 시작, GPS 현재 위치 보기 등 앱 작업에 사용
- drawer
- 화면 왼쪽에 스와이프하여 목록을 볼 수 있는 하위 위젯
- 일반적으로 탐색 링크, 설정, 기타 콘텐츠가 포함
- buttomNavigationBar
- 화면 하단에 내비게이션 바를 표시하는 하위 위젯
- 앱의 다른 섹션이나 화면을 나타내는 몇 가지 아이콘이 포함
- appBar
home: Scaffold(
// 코드 작성
),
Text 위젯
- 텍스트를 보여줄 때 사용하는 위젯
- 속성을 이용하여 텍스트의 모양을 바꿀 수 있음
- 속성
- style : 문자의 글꼴, 색상, 크기, 두께 등을 정의하는 TextStyle 개체
- textAlign : 문자의 가로 정렬을 설정하는 TextAlign 유형의 열거형
- textDirection : 문자의 방향, 왼쪽에서 오른쪽인지, 오른쪽에서 왼쪽인지 설정하는 TextDirection의 열거형
- softWrap : 문자가 텍스트 위젯을 초과하는 경우 다음 줄로 줄 바꿈되어야 하는지 여부를 나타내는 부울 값
- overflow : 문자가 텍스트 위젯을 초과하는 경우 텍스트를 처리하는 방법을 설정하는 TextOverflow 유형의 열거형
- maxLines : 문자가 표시할 수 있는 최대 줄 수 지정, null로 설정하면 필요한 줄만큼 크기를 차지
- textScaleFactor : 문자의 배율을 지정하는 부동 소수점 값, 1.5로 설정시 원래 크기의 150%로 표시
Text(
// 코드 작성
),
- 예시) 글씨가 30이고 볼드 효과가 들어간 빨간색 글씨로 'Hello World' 출력해보기
Text(
'Hello, World!!!',
style: TextStyle(
fontSize: 30, // 폰트 크기
fontWeight: FontWeight.bold, // 폰트 두께
color: Color.fromRGBO(255, 0, 0, 1), // 폰트 색상(R,G,B,Opacity)
), // TextStyle
), // Text
Column&Row 위젯
- Columns : 세로 열로 자식을 표시해주는 위젯
- Row : 가로 행으로 자식을 표시해주는 위젯
- 위젯을 서로 쌓고 정렬하는 데 사용
- 속성
- cildren : 자식으로 표시되는 위젯, 즉 행과 열 안에 표시되는 내용을 포함해주는 위젯
Column(
// 코드 작성
),
- 예시) 'Hello World' 아래에 새로운 열 추가하기
Column(
children: [
Center(
child: Text(
'Hello, World!!!',
style: TextStyle(
fontSize: 30, // 폰트 크기
fontWeight: FontWeight.bold, // 폰트 두께
color: Color.fromRGBO(255, 0, 0, 1), // 출력할 내용
), // TextStyle
), // Text
), // Center
Text('Second Column'),
],
), // Column
TextField 위젯
- 사용자가 텍스트를 입력할 수 있는 공간을 제공하는 위젯
- 검색 창 및 회원가입, 로그인 등
- 속성
- decoration : 텍스트필드에 표시될 설명과 제목, 테두리를 설정하는데 사용하는 InputDecoration 개체
- onChanged : 사용자가 텍스트필드에 텍스트를 입력하거나 변경할 때마다 실행되는 콜백 함수
- keyboardType : 텍스트필드를 선택할 때 표시되는 키보드 유형을 설정하는 TextInputType 유형의 열거형
- maxLines : 텍스트필드에 입력할 수 있는 최대 텍스트 줄 설정
- maxLength : 텍스트필드에 입력할 수 있는 최대 문자 수 설정
- obscureText : 암호 입력과 같이 텍스트를 가려야하는지 여부를 설정
- style : 텍스트필드에 표시되는 텍스트의 스타일을 지정하는 TextStyle 개체
- textAlign : 텍스트필드에서 텍스트의 가로를 정려하는 TextAlign 유형의 열거형
TextField(
// obscureText: true = 입력한 텍스트를 별표로 표시
decoration: InputDecoration(
// 코드 작성
// labelText: 텍스트필드 제목
// hintText: 텍스트필드를 누를 경우 나올 설명
),
),
- 예시) 위에서 추가한 'Second Column' 바로 밑에 사용자 입력 필드 두 개 추가하고 'abcd' 입력
- 첫번째 : 텍스트를 입력할 텍스트 필드 (ID 입력)
- 두번째 : 텍스트를 입력하면 별표로 바뀌어서 보이게하는 텍스트 필드 (비밀번호 입력)
Column(
children: [
Center(
child: Text(
'Hello, World!!!',
style: TextStyle(
fontSize: 30, // 폰트 크기
fontWeight: FontWeight.bold, // 폰트 두께
color: Color.fromRGBO(255, 0, 0, 1), // 출력할 내용
), // TextStyle
), // Text
), // Center
TextField(
decoration: InputDecoration(
hintText: '입력한 글자는 그대로 보입니다.',
labelText: '텍스트필드1',
), // InputDecoration
), // TextField
TextField(
obscureText: true,
decoration: InputDecoration(
hintText: '입력한 글자는 암호화 됩니다.',
labelText: '텍스트필드2',
), // InputDecoration
), // TextField
],
), // Column
Button 위젯
- 사용자 인터페이스에서 클릭 가능한 버튼을 제공하는 위젯
- 속성
- onPressed : 버튼을 눌렀을 때 실행되는 콜백 함수
- child : 버튼 내부에 표시되는 위젯
- 버튼의 종류
- Elevated Button : 배경색이 채워진 볼록한 버튼
- Text Button : 다양한 스타일로 사용자가 정의할 수 있는 텍스트가 있는 플랫 버튼
- Outlined Button : 테두리와 투명한 배경이 있는 버튼
- Icon Button : 아이콘으로 표시되는 버튼
ElevatedButton(
onPressed: () {},
child: Text('Elevated Button'),
),
TextButton(
onPressed: () {},
child: Text('Text Button'),
),
OutlinedButton(
onPressed: () {},
child: Text('OutlinedButton'),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.add),
),
예시) 위의 Columns 위젯에 각각의 버튼 추가해보기
Column(
children: [
Center(
child: Text(
'Hello, World!!!',
style: TextStyle(
fontSize: 30, // 폰트 크기
fontWeight: FontWeight.bold, // 폰트 두께
color: Color.fromRGBO(255, 0, 0, 1), // 출력할 내용
), // TextStyle
), // Text
), // Center
TextField(
decoration: InputDecoration(
hintText: '입력한 글자는 그대로 보입니다.',
labelText: '텍스트필드1',
), // InputDecoration
), // TextField
TextField(
obscureText: true,
decoration: InputDecoration(
hintText: '입력한 글자는 암호화 됩니다.',
labelText: '텍스트필드2',
), // InputDecoration
), // TextField
ElevatedButton(
onPressed: () {},
child: Text('Elevated Button'),
), // ElevatedButton
TextButton(
onPressed: () {},
child: Text('Text Button'),
), // TextButton
OutlinedButton(
onPressed: () {},
child: Text('OutlinedButton'),
), // OutlinedButton
IconButton(
onPressed: () {},
icon: Icon(Icons.add),
), // IconButton
],
), // Column
appBar 위젯
- Scaffold의 상단 앱 바를 나타내는 위젯
- 표준 앱 바 레이아웃을 제공
- 제목, 선택적 작업을 하는 아이콘, 위젯을 포함
- 속성
- title : 앱 바 중앙에 표시할 문자 또는 위젯
- backgroundColor : 앱 바의 배경색, 기본적으로 앱 테마의 기본 색상으로 설정
- elevation : 앱 바 아래의 그림자 효과, 기본적으로 4.0으로 설정
- centerTitle : 제목을 앱 바 중앙에 배치할지 여부를 결정, 부울 값으로 설정
- 예시) 앱 바의 텍스트 중앙 정렬
home: Scaffold(
appBar: AppBar(
centerTitle: true, // 앱 상단바 텍스트 중앙 정렬
title: Text('Hello World Example'), // 앱 상단바 설정
),
),
Padding 위젯
- 자식 위젯 주위에 안쪽 여백을 제공하는 데 사용
- 속성
- padding
- 자식 위젯에 적용할 안쪽 여백의 정도를 지정하는 EdgeInsets 개체
- 4면에 동일한 안쪽 여백을 적용하거나 단일 값을 사용하여 각각의 4면에 별도의 값을 적용
- EdgeInsets 개체 : 안쪽 여백의 정도를 지정하는 클래스, left right, top, bottom, all의 속성 이용
- child : padding 위젯이 안쪽 여백을 적용하는 위젯
- padding
//전방위 모두 동일하게 적용
EdgeInsets.all(8)
//특정 방위만 적용
EdgeInsets.only(
left: 8,
right: 8,
)
//위아래 또는 좌우 적용
EdgeInsets.symmetric(
vertical: 8,
horizontal: 8,
)
- Margin(바깥 여백)과 Padding(안쪽 여백), Border(테두리) 영역 확인
- 사이즈는 예시를 위한 것일뿐 신경쓰지마세요.
- 예시) 좌우에 50픽셀, 상단에 100픽셀의 안쪽 여백 만들기
body: Padding(
padding: const EdgeInsets.only(
left: 50,
right: 50,
top: 100,
), // EdgeInsets.only
child: Columns(
// 하위 위젯 나열
// 중략
), // Columns
), // Padding
Container 위젯
- 다른 위젯을 데코레이션하고 배치하고 크기를 조정하는 방법등을 제공하는 위젯
- 일반적으로 다른 위젯과 함께 그룹화하여 바깥쪽 여백, 안쪽 여백, 테두리 및 배경색과 같은 시각적 속성을 적용하는데 사용
- 속성
- alignment : 컨테이너 내 자식의 위치를 제어
- padding : 컨테이너의 가장자리와 그 자식 사이의 안쪽 여백 정의
- color : 컨테이너의 배경색을 설정
- width : 컨테이너의 너비 설정, double.infinity : 부모의 사용가능한 모든 공간을 너비로 사용
- height : 컨테이너의 높이 설정
- decoration : 테두리, 배경 이미지 또는 기타 데코레이션을 컨테이너에 추가하는데 사용
- 클래스
- border : 위젯의 테두리를 정의하는데 사용, 종종 Container와 함께 사용하여 테두리를 추가
// 크기가 100x100인 컨테이너
Container(
width: 100.0,
height: 100.0,
color: Colors.blue,
child: Text('크기가 100x100인 컨테이너'),
), // Container
- 예시) Elevated Button을 Container 위젯으로 감싸고 테두리와 가로 너비를 최대한 크게 조절해보기
- 보더 클래스는 위젯이 아니기 때문에 이 포스팅에서는 따로 설명하지 않습니다.
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 2.0,
style: BorderStyle.solid,
), // Border.all
), // BoxDecoration
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: Text('Elevated Button'),
), // ElevatedButton
), // Container
// 코드 생략
Image 위젯
- 애플리케이션에 이미지를 표시하는 데 사용
- 리소스, 네트워크, 메모리와 같은 다양한 소스에서 이미지를 로드할 수 있음
- 속성
- image
- 표시할 이미지 소스
- File, AssertImage, NetworkImage, MemoryImage, ImageProvider 객체로 표시
- width, height
- 이미지의 너비(width)와 높이(height)
- 하나의 값만 지정된 경우 이미지는 해당 값에 비례하여 크기 조정
- fit
- 컨테이너에 맞게 이미지 크기를 조정
- 옵션
- BoxFit.contain : 전체 이미지가 상위 위젯 크기에 맞도록 이미지 크기 조정
- BoxFit.cover : 상위 위젯에 전체를 덮으면서 이미지 크기 조정, 크기가 맞지 않으면 이미지의 일부 짤림 발생
- BoxFit.fill : 부모 위젯을 완전히 채우도록 이미지 크기 조정, 가로 세로 비율 왜곡 발생 가능성 존재
- BoxFit.fitHeight : 가로 세로 비율을 유지하면서 상위 위젯의 높이에 맞게 이미지 크기 조정, 이미지는 수평 중앙에 배치
- BoxFit.fitWidth : 가로 세로 비율을 유지하면서 상위 위젯의 너비에 맞게 이미지 크기 조정, 이미지는 수직 중앙에 배치
- BoxFit.none : 이미지 스케일링을 적용하지 않고 이미지 원래 크기로 표시
- BoxFit.scaleDown : 상위 위젯에 맞도록 필요시 가로 세로 비율을 유지하면서 이미지 축소
- alignment
- 컨테이너 내 이미지를 정렬
- 옵션
- Alignment.topLeft : 컨테이너 왼쪽 상단 모서리 정렬
- Alignment.topRight : 컨테이너 오른쪽 상단 모서리 정렬
- Alignment.bottomLeft : 컨테이너 왼쪽 하단 모서리 정렬
- Alignment.bottomRight : 컨테이너 오른쪽 하단 모서리 정렬
- Alignment.center : 컨테이너 중앙 수평 수직 정렬
- Alignment.topCenter : 수평으로는 컨테이너 중앙, 수직으로는 컨테이너 상단 정렬
- Alignment.bottomCenter : 수평으로는 컨테이너 중앙, 수직으로는 컨테이너 하단 정렬
- Alignment.centerLeft : 수평으로는 컨테이너 중앙, 수직으로는 컨테이너 왼쪽 정렬
- Alignment.centerRight : 수평으로는 컨테이너 중앙, 수직으로는 컨테이너 오른쪽 정렬
- repeat
- 이미지가 컨테이너보다 작은 경우 컨테이너를 채우기 위해 이미지 반복 여부 설정
- 옵션
- ImageRepeat.noRepeat : 이미지 반복 없이 원래 크기로 한 번 표시
- ImageRepeat.repeat : 이미지를 수평 수직으로 반복
- ImageRepeat.repeatX : 이미지 가로로만 반복
- image
//Image.asset()
//Image.file()
//Image.memory()
//Image.network()
/// Image.network('https://localhost:3000/my_image.png')
- 예시) 최상단에 인터넷 URL로 이미지 넣기
- 이미지는 원하는 이미지를 찾아서 넣기
Column(
children: [
Image.network(
'https://static.wikia.nocookie.net/pokemon/images/a/aa/%EC%82%90_%EA%B3%B5%EC%8B%9D_%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8.png/revision/latest/scale-to-width-down/200?cb=20170406071411&path-prefix=ko'),
// 코드 생략
],
) // Column
SingleChildScrollView 위젯
- 사용 가능한 공간이 충분하지 않을 때 자식을 스크롤 할 수 있게 해주는 위젯
- 컨테이너의 크기를 초과할 수 있는 위젯이 콘텐츠를 보기 위해 스크롤을 활성화하려는 경우에 사용
SingleChildScrollView(
child: Column(
children: [
// 하위 위젯 코드 작성
],
),
)
왜 SingleChildScrollView를 쓰는가?
위에서 예시를 위해 제작한 앱을 살펴보면, 텍스트필드1을 선택시 키보드 입력 창이 출력되어 하위의 위젯들은 확인할 수 없는 상태가 됩니다. 이런 경우를 위해 'SingleChildScrollView' 위젯을 이용해서 Column, Row 등 그룹화 하는 위젯을 자식으로 두고 하위의 위젯들이 화면 크기를 초과하면 'SingleChildScrollView'을 통해 사용자가 스크롤하여 나머지 콘텐츠를 볼 수 있습니다.
(예시: 아래의 그림에서 키보드 입력으로 인한 화면 초과, 스크롤이 되지 않아 밑의 컨텐츠를 확인할 수 없는 상태)
- 예시) 최상단에 'SingleChildScrollView' 위젯으로 감싸서 모든 하위 위젯들을 스크롤로 컨텐츠 확인해보기
- 즉, 쉽게 말해서 최상위 부모 위젯 감싸기(포스팅에서는 Padding)
- Tip : 최상위 부모는 코드의 제일 아래쪽을 보면 유추 가능함
- 좌측의 노란 전구 - Wrap with widget
- 생성된 위젯 이름을 SingleChildScrollView로 변경
home: Scaffold(
appBar: AppBar(
centerTitle: true, // 앱 상단바 텍스트 중앙 정렬
title: Text('Hello World Example'), // 앱 상단바 설정
),
body: SingleChildScrollView(
child: Padding(
// 코드 생략
), // Padding
, // SingleChildScrollView
), // Scaffold
전체 소스 코드
- main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'hello_flutter', // 앱의 아이콘 이름
home: Scaffold(
appBar: AppBar(
centerTitle: true, // 앱 상단바 텍스트 중앙 정렬
title: Text('Hello World Example'), // 앱 상단바 설정
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(
left: 50,
right: 50,
top: 100,
),
child: Column(
children: [
Image.network(
'https://static.wikia.nocookie.net/pokemon/images/a/aa/%EC%82%90_%EA%B3%B5%EC%8B%9D_%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8.png/revision/latest/scale-to-width-down/200?cb=20170406071411&path-prefix=ko'),
Center(
child: Text(
'Hello, World!!!',
style: TextStyle(
fontSize: 30, // 폰트 크기
fontWeight: FontWeight.bold, // 폰트 두께
color: Color.fromRGBO(255, 0, 0, 1), // 출력할 내용
),
),
),
TextField(
decoration: InputDecoration(
hintText: '입력한 글자는 그대로 보입니다.',
labelText: '텍스트필드1',
),
),
TextField(
obscureText: true,
decoration: InputDecoration(
hintText: '입력한 글자는 암호화 됩니다.',
labelText: '텍스트필드2',
),
),
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 2.0,
style: BorderStyle.solid,
),
),
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: Text('Elevated Button'),
),
),
TextButton(
onPressed: () {},
child: Text('Text Button'),
),
OutlinedButton(
onPressed: () {},
child: Text('OutlinedButton'),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.add),
),
],
),
),
),
),
);
}
}
참고
반응형