Flutter에서 반응형 배너 UI와 애니메이션 구현

2025. 1. 13. 13:47·Flutter
728x90
반응형

Flutter를 활용하여 배너 UI를 구현하고, 배너 전환 애니메이션까지 적용한 과정을 공유합니다. 이번 작업에서는 반응형 디자인과 자연스러운 사용자 경험을 위해 애니메이션 효과를 추가하고, UI 구조를 체계적으로 구성했습니다.


구현 목표

  1. 상단 제목과 날짜 표시: 배너의 상단에 텍스트 형태로 제목과 날짜를 표시.
  2. 하단 반투명 배경과 버튼: 하단에는 반투명한 검정 배경 위에 "글자" 버튼과 숫자 수를 표시.
  3. 반응형 UI: 다양한 화면 크기를 지원하기 위해 ScreenUtil을 적용.
  4. 애니메이션 효과: 배너 전환 시 자연스러운 애니메이션 적용.
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class CustomSlideCard extends StatelessWidget {
  final String imagePath;
  final String title;
  final String dateRange;
  final VoidCallback onTap;
  final int visitCount;
  final int currentCount;

  const CustomSlideCard({
    super.key,
    required this.imagePath,
    required this.title,
    required this.dateRange,
    required this.onTap,
    required this.visitCount,
    required this.currentCount,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        width: double.infinity,
        height: 200.h,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(16.0.r),
          image: DecorationImage(
            image: AssetImage(imagePath),
            fit: BoxFit.cover,
            colorFilter: ColorFilter.mode(
              Colors.black.withOpacity(0.4),
              BlendMode.darken,
            ),
          ),
        ),
        child: Stack(
          children: [
            // 상단 제목 및 날짜
            Positioned(
              top: 16.h,
              left: 16.w,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 18.sp,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  SizedBox(height: 8.h),
                  Text(
                    dateRange,
                    style: TextStyle(
                      color: Colors.white70,
                      fontSize: 14.sp,
                    ),
                  ),
                ],
              ),
            ),
            // 하단 반투명 배경 및 버튼 섹션
            Positioned(
              bottom: 0,
              left: 0,
              right: 0,
              child: Container(
                padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 16.w),
                decoration: BoxDecoration(
                  color: Colors.black.withOpacity(0.6),
                  borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(16.0.r),
                    bottomRight: Radius.circular(16.0.r),
                  ),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          "글자",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 16.sp,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        const Icon(
                          Icons.arrow_forward_ios,
                          color: Colors.white,
                          size: 16,
                        ),
                      ],
                    ),
                    SizedBox(height: 8.h),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Row(
                          children: [
                            const Icon(Icons.people, color: Colors.white, size: 16),
                            SizedBox(width: 8.w),
                            Text(
                              "$visitCount명 방문",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 14.sp,
                              ),
                            ),
                          ],
                        ),
                        Row(
                          children: [
                            const Icon(Icons.settings, color: Colors.white, size: 16),
                            SizedBox(width: 8.w),
                            Text(
                              "$currentCount명 숫자",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 14.sp,
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

2. 애니메이션 효과

애니메이션 효과를 구현하기 위해 CarouselSlider와 함께 전환 애니메이션을 추가했습니다.

import 'package:carousel_slider/carousel_slider.dart';

class CustomCarouselSlider extends StatelessWidget {
  final List<Widget> slides;
  final Duration autoPlayInterval;
  final Duration animationDuration;

  const CustomCarouselSlider({
    super.key,
    required this.slides,
    this.autoPlayInterval = const Duration(seconds: 3),
    this.animationDuration = const Duration(milliseconds: 800),
  });

  @override
  Widget build(BuildContext context) {
    return CarouselSlider(
      items: slides,
      options: CarouselOptions(
        height: 200.h,
        autoPlay: true,
        autoPlayInterval: autoPlayInterval,
        autoPlayAnimationDuration: animationDuration,
        viewportFraction: 1.0,
      ),
    );
  }
}

 

주요 구현 내용

  1. 배너 UI:
    • 상단에는 제목과 날짜를 배치.
    • 하단에는 반투명 배경과 함께 버튼 및 정보를 표시.
  2. 반응형 디자인:
    • ScreenUtil을 사용하여 다양한 화면 크기를 지원.
  3. 배너 전환 애니메이션:
    • autoPlayInterval과 autoPlayAnimationDuration을 설정하여 부드러운 전환 효과 구현.
  4. 확장성:
    • 클릭 이벤트와 데이터(방문자 수, 숫자 등)를 동적으로 설정할 수 있도록 구성.
728x90
반응형
LIST

'Flutter' 카테고리의 다른 글

Flutter에서 SizedBox.shrink()를 활용하여 빈 공간 추가하는 방법  (2) 2025.02.07
Flutter에서 날짜와 시간 선택 유효성 검사 구현하기  (1) 2025.01.20
Flutter에서 갤러리 이미지 선택 UI: 간격과 레이아웃 최적화 (이미지 썸네일)  (1) 2025.01.07
이미지 접근 (Ios , Android) 권한  (0) 2025.01.07
iOS Xcode 시뮬레이터 키보드 안보일때  (1) 2025.01.07
'Flutter' 카테고리의 다른 글
  • Flutter에서 SizedBox.shrink()를 활용하여 빈 공간 추가하는 방법
  • Flutter에서 날짜와 시간 선택 유효성 검사 구현하기
  • Flutter에서 갤러리 이미지 선택 UI: 간격과 레이아웃 최적화 (이미지 썸네일)
  • 이미지 접근 (Ios , Android) 권한
Mr. Joo
Mr. Joo
  • Mr. Joo
    삽질의 시작
    Mr. Joo
  • 전체
    오늘
    어제
    • 분류 전체보기 (214)
      • Flutter (70)
      • Android (9)
      • Swift (4)
      • React (11)
      • 인공지능 (4)
      • CS (10)
      • 개발 뉴스 (103)
      • IT 기기 (1)
      • 알면 유용한 정보 (2)
  • 인기 글

  • 태그

    오늘의 이슈
    뉴스
    이슈
    플러터
    DART
    오늘의 기술 뉴스
    앱개발
    react
    앱 개발
    오늘의 개발 뉴스
    기술 뉴스
    개발
    Dart 기초
    Flutter
    개발 뉴스
    뉴스 모음
    기술
    앱
    오늘의 뉴스
    개발 이슈
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
Mr. Joo
Flutter에서 반응형 배너 UI와 애니메이션 구현
상단으로

티스토리툴바