ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [개발일지] flutter 앱개발 2주차
    Study/Development 2022. 9. 12. 23:53

    <스파르타코딩 flutter 강의 수강일지>

     

    2주차: 사용자가 보는 화면 만들기

    1. Flutter Widget

    1) Stateless vs Stateful

    Stateless: 상태변화 X -> 새로고침 X Stateful: 상태변화 O -> 새로고침 O

    *setState()는 Stateful에서 동작한다.

    VSC에서 st 까지만 입력하면, Stateful Widget과 Stateless Widget의 기본 프리셋이 자동완성 된다.

    /// Stateless Widget
    
    class MyWidget extends StatelessWidget {
      const MyWidget({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        
      }
    }
    
    
    /// Stateful Widget
    class MyWidget extends StatefulWidget {
      const MyWidget({Key? key}) : super(key: key);
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      @override
      Widget build(BuildContext context) {
        
      }
    }

     

    2) 기본 위젯: Text / Container / Icon / Image

    // Text
    Text(
      '텍스트 위젯',
      style: TextStyle(
        fontSize: 35, // 폰트 크기
        fontWeight: FontWeight.bold, // 폰트 두께
        color: Colors.amber, // 폰트 색상
      ),
    ),
    
    // Container
    Container(
      width: 200, // 폭
      height: 200, // 높이
      color: Colors.pinkAccent, // 박스 색상
      child: Text("I Love Flutter!"), // 자식 위젯
      
      padding: EdgeInsets.all(20), // 박스 안쪽 영역
      margin: EdgeInsets.all(50), // 박스 바깥 영역
      alignment: Alignment.topLeft, // child 정렬
    ),
    
    // Material Icon
    Icon(
      Icons.home,
      color: Colors.blue,
      size: 50,
    ),
    
    // Cupertino Icon
    Icon(
      CupertinoIcons.house,
      color: Colors.pink,
      size: 50,
    ),
    
    // Image Network
    Image.network(
        'https://i.ibb.co/CwzHq4z/trans-logo-512.png',
        width: 150,
      ),

     

    *EdgeInsets (Padding/Margin)

    // 전방위
    EdgeInsets.all(8)
    
    // 특정 방위만 적용
    EdgeInsets.only(
      left: 8,
      right: 8,
    )
    
    //수직, 수평으로 적용
    EdgeInsets.symmetric(
    	vertical: 8,
    	horizontal: 8,
    )

     

    *BoxDecoration

    Container(
      width: 200,
      height: 200,
      // color : Colors.amber, // decoration와 함께 사용 불가
      decoration: BoxDecoration(
        color: Colors.amber, // decoration 안에 color를 활용해주세요.
        borderRadius: BorderRadius.circular(50), // 모서리를 둥글게
        border: Border.all(color: Colors.blue, width: 5), // 테두리
        boxShadow: [
          BoxShadow(
            // 그림자 효과
            color: Colors.grey.withOpacity(0.7), // 투명도 70% 회색
            spreadRadius: 5, // 퍼짐 효과
            blurRadius: 7, // 뭉갬 효과
            offset: Offset(5, 5), // 그림자를 우측 5 아래 5만큼 이동
          ),
        ],
      ),
    );

     

    Material Icon 모아보기

    https://fonts.google.com/icons?selected=Material+Icons 

     

    Material Symbols and Icons - Google Fonts

    Material Symbols are our newest icons consolidating over 2,500 glyphs in a single font file with a wide range of design variants.

    fonts.google.com

     

    Cupertino Icon 모아보기

    https://shuuji3.xyz/flutter-packages/third_party/packages/cupertino_icons/

     

    Cupertino Icons 1.0.0 Gallery

     

    shuuji3.xyz

     

     

    3) 레이아웃(Layout) 위젯: Scaffold / Column / Row / Stack / SingleChildScrollView

    *SingleChildScrollView와 Listview.builder는 같이 쓰지 않는다.

     

    Scaffold

    Scaffold(
    	appBar: AppBar(), // 상단 바
    	body: Text(), //화면 중앙에 가장 큰 면적
    	bottomNavigationBar: BottomNavigationBar(), //하단 바
    	floatingActionButton: FloatingActionButton(), //우측 하단
    ),

    AppBar 구성

    Column / Row

    Column(
      children: [
        // 자식 위젯들
        Text("위젯1"),
        Text("위젯2"),
      ],
      
      // 세로 방향에 대한 크기
      mainAxisSize: MainAxisSize.max, // 부모를 가득
      mainAxisSize: MainAxisSize.min, // 자식 크기만큼
      
      // 세로 방향 정렬
      mainAxisAlignment: MainAxisAlignment.center, // 중앙
      mainAxisAlignment: MainAxisAlignment.start,  // 시작
      mainAxisAlignment: MainAxisAlignment.end, // 끝
      mainAxisAlignment: MainAxisAlignment.spaceBetween, // 양 끝에 배치하고 등분
      mainAxisAlignment: MainAxisAlignment.spaceAround, // 균등하게 나누고 공간의 절반을 뒤에
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 등분
      
      // 가로 방향 정렬
      crossAxisAlignment: CrossAxisAlignment.center, // 중앙
      crossAxisAlignment: CrossAxisAlignment.start, // 시작
      crossAxisAlignment: CrossAxisAlignment.end, // 끝
      crossAxisAlignment: CrossAxisAlignment.stretch, // 늘려 가득 채움
    ),
    
    // Column과 가로 세로 반대
    Row(
      children: [
        // 자식 위젯들
        Text("위젯1"),
        Text("위젯2"),
      ],
    ),

     

    Stack: 쌓아 올림

    Stack(
      children: [ // 자식 위젯들
        Text("위젯1"),
        Text("위젯2"),
      ],
    ),

     

    SingleChildScrollView: 위젯이 스크린보다 클 때, 스크롤 할 수 있도록 함.

    SingleChildScrollView(
      child: Container(height: 10000), // 자식 위젯
    ),

     

    3. 텍스트 입력: TextField

    TextField(
      autofocus: true, // 자동 포커스
      onChanged: (text) {
        // 텍스트 변경시 실행되는 함수
      },
      onSubmitted: (text) {
        // Enter를 누를 때 실행되는 함수
      },
    ),

     

     

    4. 클릭 이벤트: Button

    // 위로 올라와 있는 듯한 버튼
    ElevatedButton(
      onPressed: () {
        print("Elevated Button 클릭");
      },
      child: Text('Elevated Button'),
    ),
    
    // 텍스트 버튼
    TextButton(
      onPressed: () {
        print("Text Button 클릭");
      },
      child: Text('Text Button'),
    ),
    
    // 아이콘 버튼
    IconButton(
      onPressed: () {
        print("Icon Button 클릭");
      },
      icon: Icon(Icons.add),
    ),

     

    5. 화면 이동: Navgator.push / pop

    // 다음 페이지로 이동
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SecondPage()), // 이동하려는 페이지
    );
    
    // 현재 화면 종료
    Navigator.pop(context); // 종료

     

    6. 공백 위젯: Spacer, Sizedbox, Divider

    // 가로 세로 일정 간격 줄 때
    SizedBox(height: 20),
    SizedBox(width: 20),
    
    // 사이 공간을 꽉 채울 때
    Spacer()
    
    // 구분선 넣을 때
    Divider()

     

     

    2. 실습과제

    ClipRRect: 모서리를 둥글게

    ClipRRect(
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(8),
        topRight: Radius.circular(8),
      ),
      child: Image.network(
        imageUrl,
        fit: BoxFit.fitHeight,
        height:
            MediaQuery.of(context).size.width * 0.4,
      ),
    ),

     

    GestureDetector: 탭, 더블탭 등 제스처에 함수 할당

      GestureDetector(
        onTap: () {
          DefaultTabController.of(context)?.animateTo(0);
        }, // 탭할 때 함수 실행
        child: Column(
          children: [
            Icon(Icons.person, color: Colors.white),
            Text(
              '라이브러리',
              style: TextStyle(color: Colors.white),
            ),
          ],
        ),
      ),

     

    SafeArea: 노치 혹은 상단 스테이터스 바 영역 비워줌

    SafeArea(
      child: Scaffold(
        appBar: AppBar(),
      ),
    );

     

    Positioned: 위치 조정

      Stack(
        children: [
          Positioned(
            left: 28.0,
            top: 20.0,
            child: UserProfileImage(
              imageURL: room.speakers[1].imageUrl,
              size: 48,
            ),
          ),
          UserProfileImage(
            imageURL: room.speakers[0].imageUrl,
            size: 48,
          )
        ],
      ),

     

    TabBar / TabBarView: 탭하여 다른 내용 보여줌

    // AppBar에 넣음
    TabBar(
                tabs: [
                  Tab(text: "Chats"),
                  Tab(text: "Requests"),
                ],
              ),
            ),
            
            
    // Body에 넣음
    TabBarView(
      children: [
        ListView.builder(
          itemCount: backChannelRoomsList.length,
          itemBuilder: (context, index) {
            return BackChannelRoomCard(
                backChannelRoom: backChannelRoomsList[index]);
          },
        ),
        Center(
          child: Text(
            "👍 You're all good!\nYou don't have any new\nmessage requests.",
            textAlign: TextAlign.center,
          ),
        ),
      ],
    ),

     

    ListTile: 리스트 형식의 타일

    ListTile(
        leading: FlutterLogo(size: 72.0),
        title: Text('Three-line ListTile'),
        subtitle: Text(
          'A sufficiently long subtitle warrants three lines.'
        ),
        trailing: Icon(Icons.more_vert),
        isThreeLine: true,
      ),

    ListTitle 구성

     

     

    반응형

    댓글

© 2023. titann all rights reserved