Slivers

  • Flutter공홈 기준으로 Development > UI > Advenced UI에서 소개되는 Slivers
  • 영상 3개와 함께 설명이 아주 잘 나와있습니다.
  • slivers = 스크롤의 끝판왕

https://flutter.dev/docs/development/ui/advanced/slivers


Slivers explained - Making dynamic layouts

A 50-minute episode of The Boring Show where Ian Hickson, Flutter’s Tech Lead, and Filip Hracek discuss the power of slivers.

  • flutter Tech Lead, Ian HicksonFilip Hracek 함께 slivers power에 대해 논의하는 50분 에피소드 영상
  • 좀 더 자세히 이야기를 듣고 이해하고싶다면 무조건 영상보는 것을 추천
  • 단순 사용하고 끝이 아닌 이해할려고 영상을 짧게 봤는데 꿀팁 등 좋은 내용이 많이 담겨 있어서 요약해서 작성해보려고 합니다. (오번역 발견 시 댓글 남겨주세요! 👀)

1. How flutter does the layout in general

Slivers이 무엇인지 알기 전에,
일반적으로 flutter가 레이아웃을 어떻게 처리하는지 알아봅시다

  • flutter엔 render objects(렌더링 객체)가 있습니다.
  • render objects는 대부분 render boxes(e.g container, sizedbox)에 표시
    • render boxes에는 모서리, 너비, 높이가 있고 배치하는 방법은 min and max 너비, min and max 높이 그리고 나서 children을 바라보고 배치합니다.
    • 그리고 나서 너비와 높이 등 주어진 제약조건 내에 width와 height를 결정합니다.

= 위 배치 방식은 box에선 잘 돌아갑니다.


= 스크롤에 적합하지않습니다.
(특히 appbar 및 기타 별난 스크롤 효과와 같은 작업을 할때)

  • 그래서 스크롤링 할 수 있는 Sliver protocol 있습니다.
    • 다양한 축(=방향, 앞뒤, 교차 축 방향 등)이 있고 자세한 내용은 RanderSilver 문서를 통해 사용하는 프로토콜들을 볼 수 있습니다.
    • min,max,width,height 사용하는 대신 많은 축을 사용하는 SliverConstraints(제약조건) 에선 얼마나 큰지 레이아웃 범위를 지정 합니다.
  • 모든것을 지정할 수 있는 이유?
    • 예를들어 AppBar는 얼마나 스크롤했는지, 그래서 얼마나 커져야하는지 알고 그 다음 slivers가 어딨는지 알아야합니다.
    • 또한 목록에서 컨텐츠를 지연로드 작업을 수행하는데 사용합니다
  • TMI 👻
    • ListView가 있을 때 실제로 알고있는 box, 수많은 boxes를 모두 인스턴스화 하지 않습니다.
      우리는 캐싱 목적과 접근성을 위해 약간 전, 후 그리고 화면에 있는 것들만 인스턴스 합니다.
    • 화면에 있는 것들만 인스턴스하고 이 프로토콜을 사용해 얼마나 멀리 스크롤 했는지 확인합니다. 그러고 필요에 따라 얼마나 남았는지 확인하면서 실제로 필요한 box만 렌더링합니다.
    • ListView조차 Slivers를 사용하고 있습니다. (flutter 에서 스크롤 되는 거의 모든 것들은 slivers를 사용하고 있다. 예외적으로 viewport(=단일 항목 스크롤)나 뭐시기 빼고)

요약

  • 렌더링 박스는 부모에 의해 constraint가 주어지며, 해당 조건 내에서 크기가 제어됩니다. constraint는 최소 너비와 최대 너비 그리고 높이로 구성되며, 크기는 특정 너비와 높이로 구성됩니다.
  • 하지만 slivers에겐 모든 것을 결정할 수 있습니다.

2. first of all, use the SliverAppBar, right.

우리가 할일은 우선 AppBar -> SliverAppBar 사용해보기!
= SliverAppBar는 기본적으로 AppBar와 동일하게 작동합니다. (argments 등 관점으로)

+ 06:26 😂
What happens if we use the SliverAppBar first of all?
IAN: It's not going to be happy at all.

  • SliverAppBar 실 사용 예제는 CustomScrollView 문서에 있습니다.

  • Scaffold 제거합니까?

    • 필요하지 않다면 제거 가능
    • 뭐 floating action button or draw 등 좋아하면 유지해도 됨
      (단, 사용할 때 CustomScrollView안에 SliverAppBar 넣어야 함
      CustomScrollView 보다 바깥에 있는 Scaffold 자리에 넣게 되면 스크롤링 안되고 어떻게 작동할지 모르게 됨)
  • args naming TMI
    • So a CustomScrollView takes many children. Normally we use the name children
    • Sliver parent → we use the word slivers instead of children
    • = 일반적으로 children을 많이 쓰지만 여기선 Sliver가 부모이니 slivers 단어 사용

[sample]

CustomScrollView(
  slivers: <Widget>[
    const SliverAppBar(
      pinned: true, 
      expandedHeight: 250.0,
      flexibleSpace: FlexibleSpaceBar(
        title: Text('Demo'),
      ),
    ),

2. And now what do I do if I want to have my list here?

list를 만들려면 SliverList 사용해야합니다.
= SliverList는 기본적으로 ListView와 동일한 args가 있습니다.

  • delegate에서 위젯을 그리는 2가지 방식 있음
    • // 테스트해보니 3가지네 ㅎㅎ; (2018년 12월 영상 기준 2가지 방식이라고 소개)
    • SliverChildBuilderDelegate(builder) = ListViewBuilder와 같은 builder
      SliverChildListDelegate(children) = 실제 widget list를 갖고있는 목록 (children)

권장하는 방식 (ListView 또한 포함)

  1. List variant 보다 Builder variant를 사용할 것

    • 일반적으로 저는 항상 사람들에게 권장합니다. use the Builder variant rather than the List variant
    • both of them are lazy in that they (둘다 lazy 한다는 점에서) both don't render the render (둘다 렌더링을 렌더링하지않습니다.)
      = 미리 랜더박스를 인스턴스화 하지않습니다.
    • 하지만 List version은 위젯을 인스턴스화 합니다. 전체 위젯 목록을 생성해야하기 때문입니다.
  2. childCount 명시해 줄 것

    • 사실은 number를 꼭 제공할 필욘 없습니다. (= you actually don't necessarily need to give that number.)
    • 빌더가 null을 반환하면 last child라고 가정합니다.
    • 그럼에도 count를 제공하는 이유는 스크롤 막대를 사용할 수 있도록 list의 길이를 예측할 수 있습니다.
    • better and so forth. (고로 명시해주는게 더 좋습니다.)
...
SliverGrid(
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 200.0,
        mainAxisSpacing: 10.0,
        crossAxisSpacing: 10.0,
        childAspectRatio: 4.0,
      ),
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return Container(
            alignment: Alignment.center,
            color: Colors.teal[100 * (index % 9)],
            child: Text('Grid Item $index'),
          );
        },
        childCount: 20,
      ),
    ),
...

+ 자잘하게 args 알아보기

  • SliverAppBar
    • pinned:true 항상 목록 맨위에 유지되고 스크롤 내리면 그림자까지 구현 (TMI. 구현하는데 며칠걸림)
    • floating:true pinned 설정 빼고 floating true 해놓을 경우 스크롤을 아래로 내릴 경우 없어지고 위로 올리면 다시 나왔다가 또 다시 내리면 사라지는 기능
    • expandedHeight: 200 appBar가 크기만큼 확장되고 스크롤 내릴 경우 크기가 줄어든다.
    • flexibleSpace: Widget() expanded 크기 만큼 그 위 나타날 위젯 (보통 이미지를 넣어서 사용)

return CustomScrollView(
      slivers: [
        SliverAppBar(
          floating: true,
          expandedHeight: 200,
          flexibleSpace: Placeholder(),
        ),
      ],
    );

3. Sliver 다른 위젯들?

여태 sliver는 outside로, 예외적으로 inside 가져가는 Sliver는?

= The main example is SliverPadding.

  • Padding위젯과 유사하게 작동합니다.
  • SliverList를 래핑할 수도 있습니다.

sliver중 가장 심플한 Sliver는?

= That's the simplest Sliver, a SliverToBoxAdapter.

  • 내부에 box가 있어야하므로 원하는 child를 넣을 수 있습니다.

4. custom Sliver 만들기

20:44

OK, so all right, I think we covered SliverAppBar and, like the crazy things that you can do with Slivers.
Let's create our own Sliver.

  • 이 다음 부턴 Sliver를 사용하는게 아닌 mixin하고 상속받아 제작하는데
    원하시는 분들은 20:44 이후부터 영상 봐주세요🙂 (전 여기까지..ㅎㅎ)
  • 요약하자면 Sliver 중 SliverToBoxAdapter가 제일 쉬운 방법이니깐 SliverToBoxAdapter 구현체 소스코드 보고 copy and paste하고 새 class 만들어서 원하는 부분 수정하면서 실험하십니다. 내부 소스코드 보면서 지속적으로 캐시며 페인팅이며 설명해주십니다.



그럼 다음번엔 Sliver 이론말고 실제 사용하는 소스코드 위주 포스팅으로 찾아뵙겠습니다.
좋아요와 댓글로 많이 의견 남겨주세요🙋🏻‍♀️❤️

profile
𝙸 𝚊𝚖 𝚊 𝚌𝚞𝚛𝚒𝚘𝚞𝚜 𝚍𝚎𝚟𝚎𝚕𝚘𝚙𝚎𝚛 𝚠𝚑𝚘 𝚎𝚗𝚓𝚘𝚢𝚜 𝚍𝚎𝚏𝚒𝚗𝚒𝚗𝚐 𝚊 𝚙𝚛𝚘𝚋𝚕𝚎𝚖. 🇰🇷👩🏻‍💻

5개의 댓글

comment-user-thumbnail
2021년 4월 29일

-ㅂ-)b

1개의 답글
comment-user-thumbnail
2021년 7월 6일

꼼꼼한 정리 감사합니다. :)

답글 달기
comment-user-thumbnail
2021년 11월 24일

flutter 애매한 부분 검색하면 나오는 블로그 대단합니다 ㅋㅋㅋㅋㅋㅋ

답글 달기
comment-user-thumbnail
2022년 6월 9일

안녕하세요. listview.builder를 사용하여 이미지(네트워크에서 불러온 이미지)를 불러올때 스크롤을 아래로 내렸다가 올리면 지연로딩이라고 해야하나요 이미지를 캐시하지 못하고 사라진이미지가 늦게뜨는데 이걸 해결할 방법이 있나요? (인스타그램을 보면 스크롤 막 내려닸가 올려도 이미지는 계속 노출되고있는거처럼)

제가 사용해본방법은
1. AutomaticKeepAliveClientMixin 사용했는데 안먹힘.
2. listview.builder내 cacheExtent 사용했는데 안먹힘.
3. addAutomaticKeepAlives: true 안먹힘.

*이미지 용량이 크면 lazy로딩이 발생되는거 같긴한데..해결할 방법이 없네요..

답글 달기