SELF STUDY/Flutter

[Flutter] 넷플릭스 클론 코딩 #6 | 원형 , 사각형 이미지 슬라이더 위젯 추가 | crossAxisAlignment | InkWell | CircleAvatar

호이호이호잇 2024. 4. 27. 07:30
728x90
반응형

이번에는 넷플릭스 홈 화면에 있는 원형 슬라이더와 사각형 슬라이더를 만들어보는 시간!

아래 화면에 있는 것이 사각형 슬라이더 라고 한다.

출처 : 앱 스토어 넷플릭스

 

원형 슬라이더 구현 

column으로 타이틀 (위 사진에서는 Popular on Netflix) 과 아래 포스터 리스트를 구현을 해줌.

Title
Poster 1 Poster 2 Poster 3

 

- 시작 축은 start로 지정 (참고 : https://codingstorywithme.tistory.com/77)

- 포스터 들은 SizedBox를 이용해 구현 (https://api.flutter.dev/flutter/widgets/SizedBox-class.html)

class CircleSlider extends StatelessWidget {
  final List<Movie> movies;
  const CircleSlider(this.movies, {super.key}); // 아래에서 데이터 사용을 위해 데이터 지정을 해줌

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(7),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              const Text('Preview'),
              SizedBox(
                  height: 120,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: makeCircleImages(movies),
                  ))
            ]));
  }
}

 


원형 포스터 리스트

각각의 원형 포스터 리스트는 따로 함수로 만들어주었다.

 

- InkWell 을 사용하여 각각의 영역 터치 가능하도록 구현 

InkWell

https://api.flutter.dev/flutter/material/InkWell-class.html

: 터치에 반응하는 네모난 영역이라고 함.

: 터치하면 전체 네모난 영역이 highlight 색으로 변하고, 터치한 지점으로 부터 splash 색으로 원형이 커진다.

-> 구현이 끝난 후 실행해서 테스트 해본 영상 

 

- CircleAvatar 사용하여 원형 포스터 구현

CircleAvatar

https://api.flutter.dev/flutter/material/CircleAvatar-class.html 

: If foregroundImage fails then backgroundImage is used. If backgroundImage fails too, backgroundColor is used.

: 포그라운드 이미지 로딩 실패 -> 백그라운드 이미지 사용 / 백그라운드 이미지 로딩 실패 -> 백그라운드 컬러 사용

 
List<Widget> makeCircleImages(List<Movie> movies) {
  List<Widget> results = [];

  for (var i = 0; i < movies.length; i++) {
    results.add(
      InkWell(
        onTap: () {}, // clickable
        child: Container(
          padding: const EdgeInsets.only(right: 10),
          child: Align(
              alignment: Alignment.center,
              child: CircleAvatar(
                  backgroundImage: AssetImage('images/${movies[i].poster}'),
                  radius: 48)),
        )));
  }

  return results;
}

 


사각형 포스터 

사각형 포스터도 위와 동일한데 원형 포스터 리스트를 만들어주는 부분만 사각형 포스터 리스트를 만들어주도록 변경하면 된다.

간단하게 위에서 CircleAvatar를 지우고, 그냥 사진을 불러오면 된다.

List<Widget> makeBoxImages(List<Movie> movies) {
  List<Widget> results = [];

  for (var i = 0; i < movies.length; i++) {
    results.add(InkWell(
        onTap: () {},
        child: Container(
          padding: const EdgeInsets.only(right: 10),
          child: Align(
              alignment: Alignment.center,
              child: Image.asset('images/${movies[i].poster}')),
        )));
  }

  return results;
}

 


전체적인 코드

circle_slider.dart
import 'package:flutter/material.dart';
import 'package:netflix_clone/model/model_movie.dart';

class CircleSlider extends StatelessWidget {
  final List<Movie> movies;
  const CircleSlider(this.movies, {super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(7),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              const Text('Preview'),
              SizedBox(
                  height: 120,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: makeCircleImages(movies),
                  ))
            ]));
  }
}

List<Widget> makeCircleImages(List<Movie> movies) {
  List<Widget> results = [];

  for (var i = 0; i < movies.length; i++) {
    results.add(InkWell(
        onTap: () {}, // clickable
        child: Container(
          padding: const EdgeInsets.only(right: 10),
          child: Align(
              alignment: Alignment.center,
              child: CircleAvatar(
                  backgroundImage: AssetImage('images/${movies[i].poster}'),
                  radius: 48)),
        )));
  }

  return results;
}

 

box_slider.dart
import 'package:flutter/material.dart';
import 'package:netflix_clone/model/model_movie.dart';

class BoxSlider extends StatelessWidget {
  final List<Movie> movies;
  const BoxSlider(this.movies, {super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(7),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            const Text('Popular on Netflix'),
            SizedBox(
              height: 120,
              child: ListView(
                scrollDirection: Axis.horizontal,
                children: makeBoxImages(movies),
              ),
            )
          ],
        ));
  }
}

List<Widget> makeBoxImages(List<Movie> movies) {
  List<Widget> results = [];

  for (var i = 0; i < movies.length; i++) {
    results.add(InkWell(
        onTap: () {},
        child: Container(
          padding: const EdgeInsets.only(right: 10),
          child: Align(
              alignment: Alignment.center,
              child: Image.asset('images/${movies[i].poster}')),
        )));
  }

  return results;
}

 

위에서 만들어둔 기능을 이제 홈 스크린에서 불러서 사용하면 된다!

home_screen.dart
 ...
 
 @override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
    return ListView(children: <Widget>[
      Stack(children: <Widget>[CarouseImage(movies: movies), const TopBar()]),
      CircleSlider(movies),
      BoxSlider(movies)
    ]);
}

...

 

gitHub : https://github.com/leehy0321/NetflixClone/commit/ec08269c358a54185d92d81ed7c0f503d138f9b3


완성된 앱의 모습~

슬라이드도 잘 되고, 입력도 잘 되는 모습!

 

git : https://github.com/leehy0321/NetflixClone/commit/1f5e531a0fc428a4674524aca9af61bca7c1874f

728x90
반응형