본문 바로가기
스파르타 코딩 클럽 내일배움캠프 6기/[Flutter 트랙] 앱개발 종합반

[Flutter 트랙] 앱개발 종합반 2-16 - 스레드 위젯 구성해보기

by 앱 창업 부트캠프 2025. 3. 5.

이번 시간에는 스레드 앱의 위젯을 구성하는 방법을 학습합니다. 지난 시간에 구상한 대로 화면을 구성하고, 레이아웃을 조정하면서 원하는 UI를 완성합니다.

1. 프로젝트 생성 및 초기화

  • 터미널을 사용하여 프로젝트 생성.
  • lib 폴더 내에 home.dart 파일을 추가하고, 홈 화면을 구성할 준비.
  • 필요한 이미지 파일을 assets 폴더에 추가하고 pubspec.yaml에 등록.

flutter create thread_app
cd thread_app
code .

2. 테마 및 에뮬레이터 설정

  • 전체적인 스타일을 설정하기 위해 ThemeData를 적용.
  • 다크 모드를 기본값으로 설정.

MaterialApp(
  theme: ThemeData(
    scaffoldBackgroundColor: Colors.black,
    textTheme: TextTheme(
      bodyMedium: TextStyle(color: Colors.white),
    ),
  ),
);

3. 헤더 영역 구성

  • 앱의 상단에 위치하는 헤더를 Row를 사용하여 구성.
  • 제스처 디텍터를 사용하여 클릭 이벤트 추가.
  • 로고를 중앙에 정렬하기 위해 SizeBox를 활용.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    GestureDetector(
      onTap: () {},
      child: Image.asset("assets/images/profile.png", width: 40),
    ),
    SizedBox(width: 80), 
    Image.asset("assets/images/thread_logo.png", width: 100),
    Icon(Icons.more_vert, color: Colors.white),
  ],
);

4. 퀵 피드 등록 UI 구성

  • 컬럼(Column)과 로우(Row)를 사용하여 정렬.
  • 버튼과 텍스트를 조합하여 사용자가 빠르게 피드를 등록할 수 있도록 UI 설계.

Column(
  children: [
    Row(
      children: [
        Image.asset("assets/images/avatar.png", width: 40),
        SizedBox(width: 10),
        Expanded(
          child: TextField(
            decoration: InputDecoration(
              hintText: "무슨 일이 일어나고 있나요?",
              hintStyle: TextStyle(color: Colors.white70),
              border: InputBorder.none,
            ),
          ),
        ),
        Icon(Icons.image, color: Colors.white),
      ],
    ),
    Divider(color: Colors.white24),
  ],
);

5. 피드 리스트 구성

  • 피드 목록을 표시하기 위해 ListView 사용.
  • 각 피드는 프로필, 콘텐츠, 이미지, 버튼을 포함.

ListView.builder(
  itemCount: 5,
  itemBuilder: (context, index) {
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              CircleAvatar(
                backgroundImage: AssetImage("assets/images/avatar.png"),
              ),
              SizedBox(width: 10),
              Text("사용자$index", style: TextStyle(color: Colors.white)),
              Spacer(),
              Icon(Icons.more_horiz, color: Colors.white),
            ],
          ),
          SizedBox(height: 10),
          Text(
            "이것은 샘플 피드 내용입니다. #태그",
            style: TextStyle(color: Colors.white),
          ),
          SizedBox(height: 10),
          Container(
            height: 200,
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage("assets/images/sample_feed.jpg"),
                fit: BoxFit.cover,
              ),
            ),
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Row(children: [
                Icon(Icons.favorite_border, color: Colors.white),
                SizedBox(width: 5),
                Text("120", style: TextStyle(color: Colors.white)),
              ]),
              Row(children: [
                Icon(Icons.comment, color: Colors.white),
                SizedBox(width: 5),
                Text("35", style: TextStyle(color: Colors.white)),
              ]),
              Icon(Icons.share, color: Colors.white),
            ],
          ),
        ],
      ),
    );
  },
);

6. 프로필 및 상호작용 UI 구성

  • 프로필 이미지 위에 팔로우 버튼을 겹쳐 표시하기 위해 Stack 사용.
  • 클릭 가능한 요소는 GestureDetector로 감싸기.

Stack(
  children: [
    CircleAvatar(
      radius: 30,
      backgroundImage: AssetImage("assets/images/avatar.png"),
    ),
    Positioned(
      bottom: 0,
      right: 0,
      child: GestureDetector(
        onTap: () {},
        child: Container(
          padding: EdgeInsets.all(4),
          decoration: BoxDecoration(
            color: Colors.blue,
            shape: BoxShape.circle,
          ),
          child: Icon(Icons.add, color: Colors.white, size: 20),
        ),
      ),
    ),
  ],
);

7. 피드 콘텐츠 및 이미지 슬라이더

  • 여러 이미지를 스와이프할 수 있도록 PageView 적용.
  • 페이지 너비를 조정하여 다음 이미지가 일부 보이도록 설정.

Container(
  height: 250,
  child: PageView.builder(
    itemCount: 5,
    controller: PageController(viewportFraction: 0.8),
    itemBuilder: (context, index) {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 5),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          image: DecorationImage(
            image: AssetImage("assets/images/sample_feed.jpg"),
            fit: BoxFit.cover,
          ),
        ),
      );
    },
  ),
);

8. 소셜 미디어 상호작용 버튼

  • 좋아요, 댓글, 공유 등의 버튼을 Row로 정렬.
  • 각 버튼 옆에 숫자를 표시하여 상호작용 정도를 확인.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Row(children: [
      Icon(Icons.favorite_border, color: Colors.white),
      SizedBox(width: 5),
      Text("좋아요 120개", style: TextStyle(color: Colors.white)),
    ]),
    Row(children: [
      Icon(Icons.comment, color: Colors.white),
      SizedBox(width: 5),
      Text("댓글 35개", style: TextStyle(color: Colors.white)),
    ]),
    Icon(Icons.share, color: Colors.white),
  ],
);

9. 최종 결과

  • 스레드 앱의 피드 화면이 완성됨.
  • UI가 헤더, 퀵 피드, 피드 리스트, 이미지 슬라이더, 상호작용 버튼으로 구성됨.
  • 다음 시간에는 상태 관리를 활용하여 앱에 동적인 요소를 추가할 예정.

이제 스레드 앱의 기본 UI가 완성되었습니다. 다음 시간에는 상태 관리(State Management)를 통해 앱의 기능을 개선해보겠습니다.