HIDI Flutter Challenge (10) ListView Widget

hello_hidiยท2021๋…„ 8์›” 31์ผ
0

HIDI's Flutter Challenge

๋ชฉ๋ก ๋ณด๊ธฐ
10/12
post-thumbnail

ListView Widget

> ListView Widget

  • ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์Šคํฌ๋กค ์œ„์ ฏ

>> List View option

>> 1. ListView ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ์ด์šฉ

  • ๋ช…์‹œ์ ์œผ๋กœ children์œผ๋กœ ๋„˜๊น€
  • ์ ์€ ์ˆ˜์˜ ์•„์ดํ…œ์„ ๊ฐ€์งˆ ๋•Œ์— ์ ํ•ฉ
  • ListView ๋กœ๋“œ ์‹œ์ ์— ๋ชจ๋“  child๊ฐ€ ์ƒ์„ฑ

>>> ์˜ˆ์‹œ ์ฝ”๋“œ

   
   class ExplicitListConstructing extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return ListView(
        padding: const EdgeInsets.all(8),
        children: [
          HeaderTile(),
          PersonTile(people[0]),
          PersonTile(people[1]),
          PersonTile(people[2]),
          PersonTile(people[3]),
          PersonTile(people[4]),
          PersonTile(people[5]),
        ],
      );
    }
  }
   
   

>>> ์‹คํ–‰ ๊ฒฐ๊ณผ

image

>>> Implementation

  
  ListView({
  Key? key,
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  ScrollController? controller,
  bool? primary,
  ScrollPhysics? physics,
  bool shrinkWrap = false,
  EdgeInsetsGeometry? padding,
  this.itemExtent,
  bool addAutomaticKeepAlives = true,
  bool addRepaintBoundaries = true,
  bool addSemanticIndexes = true,
  double? cacheExtent,
  List children = const [],
  int? semanticChildCount,
  DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
  String? restorationId,
  Clip clipBehavior = Clip.hardEdge,
}) : childrenDelegate = SliverChildListDelegate(
       children,
       addAutomaticKeepAlives: addAutomaticKeepAlives,
       addRepaintBoundaries: addRepaintBoundaries,
       addSemanticIndexes: addSemanticIndexes,
     ),
     super(
       key: key,
       scrollDirection: scrollDirection,
       reverse: reverse,
       controller: controller,
       primary: primary,
       physics: physics,
       shrinkWrap: shrinkWrap,
       padding: padding,
       cacheExtent: cacheExtent,
       semanticChildCount: semanticChildCount ?? children.length,
       dragStartBehavior: dragStartBehavior,
       keyboardDismissBehavior: keyboardDismissBehavior,
       restorationId: restorationId,
       clipBehavior: clipBehavior,
     );
     
     

>>> ListView ์ฃผ์š” ์†์„ฑ

  • padding : children์„ ์‚ฝ์ž…ํ•  ๊ณต๊ฐ„ => final EdgeInsetsGeometry? padding;
  • scrollDirection : ์Šคํฌ๋กค ๋ฐฉํ–ฅ ์„ค์ • ์†์„ฑ => final Axis scrollDirection;

>> 2. ListView.builder : ํ•˜์œ„ ํ•ญ๋ชฉ์„ ๋นŒ๋“œํ•˜๋Š” IndexedWidgetBuilder๋ฅผ ์‚ฌ์šฉ

IndexedWidgetBuilder : typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
=> itemBuilder์˜ ์ƒ์„ฑ์ž
=> int index : child๊ฐ€ ListView ๋ช‡๋ฒˆ์งธ ์ž์‹์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ„

  • ํ•˜์œ„ ํ•ญ๋ชฉ ์ˆ˜๊ฐ€ ๋งŽ๊ฑฐ๋‚˜ ๋ฌดํ•œ์ธ ๊ฒฝ์šฐ์— ์ ํ•ฉ
  • itemCount : ๋ฆฌ์ŠคํŠธ์— ๊ทธ๋ ค์งˆ ์ด child ๊ฐœ์ˆ˜
  • itemBuilder : ๋ฆฌ์ŠคํŠธ์— ๊ทธ๋ ค์งˆ ํ•ญ๋ชฉ์„ Lazyํ•˜๊ฒŒ, ํ•ด๋‹น child๊ฐ€ ํ™”๋ฉด์— ๋ณด์—ฌ์•ผ ํ•  ๋•Œ ์ƒ์„ฑ

>>> ์˜ˆ์‹œ ์ฝ”๋“œ

  
  class UsingBuilderListConstructing extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: const EdgeInsets.all(8),
      itemCount: people.length + 1,
      itemBuilder: (BuildContext context, int index) {
        if (index == 0) return HeaderTile();
        return PersonTile(people[index-1]);
      },
    );
  }
}

>>> ์‹คํ–‰ ๊ฒฐ๊ณผ

image

>>> Implementation

 
 ListView.builder({
  Key? key,
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  ScrollController? controller,
  bool? primary,
  ScrollPhysics? physics,
  bool shrinkWrap = false,
  EdgeInsetsGeometry? padding,
  this.itemExtent,
  required IndexedWidgetBuilder itemBuilder,
  int? itemCount,
  bool addAutomaticKeepAlives = true,
  bool addRepaintBoundaries = true,
  bool addSemanticIndexes = true,
  double? cacheExtent,
  int? semanticChildCount,
  DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
  String? restorationId,
  Clip clipBehavior = Clip.hardEdge,
}) : assert(itemCount == null || itemCount >= 0),
     assert(semanticChildCount == null || semanticChildCount <= itemCount!),
     childrenDelegate = SliverChildBuilderDelegate(
       itemBuilder,
       childCount: itemCount,
       addAutomaticKeepAlives: addAutomaticKeepAlives,
       addRepaintBoundaries: addRepaintBoundaries,
       addSemanticIndexes: addSemanticIndexes,
     ),
     super(
       key: key,
       scrollDirection: scrollDirection,
       reverse: reverse,
       controller: controller,
       primary: primary,
       physics: physics,
       shrinkWrap: shrinkWrap,
       padding: padding,
       cacheExtent: cacheExtent,
       semanticChildCount: semanticChildCount ?? itemCount,
       dragStartBehavior: dragStartBehavior,
       keyboardDismissBehavior: keyboardDismissBehavior,
       restorationId: restorationId,
       clipBehavior: clipBehavior,
     );
#### >>> ListView.builder ์ฃผ์š” ์†์„ฑ
  • scrollDirection : ์Šคํฌ๋กค ๋ฐฉํ–ฅ ์„ค์ • ์†์„ฑ => final Axis scrollDirection;
  • padding : children์„ ์‚ฝ์ž…ํ•  ๊ณต๊ฐ„ => final EdgeInsetsGeometry? padding;
  • itemCount : child์˜ ๊ฐœ์ˆ˜ => int? itemCount
  • itemBuilder : child๋“ค์„ ์–ด๋–ป๊ฒŒ ๋ฐฐ์น˜ํ•  ์ง€ ์ •ํ•˜๋Š” ์†์„ฑ => required IndexedWidgetBuilder itemBuilder

3. >> ListView.seperated : ์ž์‹ ์ˆ˜๊ฐ€ ๊ณ ์ •๋œ ๋ชฉ๋ก์ผ ๊ฒฝ์šฐ ์ ํ•ฉ

  • ์Šคํฌ๋กค์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์„ ์ œ์ž‘ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ํ™œ์šฉ
  • ๋‘ ๊ฐœ์˜ IndexedWidgetBuilder๋ฅผ ์‚ฌ์šฉ
  • ์Šคํฌ๋กค ์˜ํ–ฅ item - ๊ตฌ๋ถ„ ๊ธฐํ˜ธ - ์Šคํฌ๋กค ์˜ํ–ฅ item ์ˆœ์œผ๋กœ ๊ณ„์† ๋ฐ˜๋ณต
  • ListView.seperated -> separatorBuilder ์ด๋Ÿฐ ์‹์œผ๋กœ ์ฝ”๋”ฉ
  • separatorCount = itemCount-1

>>> ์˜ˆ์‹œ ์ฝ”๋“œ

  
  class UsingSeparateListConstructing extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.separated(
        itemCount: people.length + 1,
        itemBuilder: (context, index) {
          if (index == 0) return HeaderTile();
          return PersonTile(people[index - 1]);
        },
        separatorBuilder: (context, index) {
          if (index == 0) return SizedBox.shrink();
          return const Divider();
        },
    );
  }
}
  
  

>>> ์‹คํ–‰ ๊ฒฐ๊ณผ

image

>>> Implementation

  
  ListView.separated({
  Key? key,
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  ScrollController? controller,
  bool? primary,
  ScrollPhysics? physics,
  bool shrinkWrap = false,
  EdgeInsetsGeometry? padding,
  required IndexedWidgetBuilder itemBuilder,
  required IndexedWidgetBuilder separatorBuilder,
  required int itemCount,
  bool addAutomaticKeepAlives = true,
  bool addRepaintBoundaries = true,
  bool addSemanticIndexes = true,
  double? cacheExtent,
  DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
  String? restorationId,
  Clip clipBehavior = Clip.hardEdge,
}) : assert(itemBuilder != null),
     assert(separatorBuilder != null),
     assert(itemCount != null && itemCount >= 0),
     itemExtent = null,
     childrenDelegate = SliverChildBuilderDelegate(
       (BuildContext context, int index) {
         final int itemIndex = index ~/ 2;
         final Widget widget;
         if (index.isEven) {
           widget = itemBuilder(context, itemIndex);
         } else {
           widget = separatorBuilder(context, itemIndex);
           assert(() {
             if (widget == null) {
               throw FlutterError('separatorBuilder cannot return null.');
             }
             return true;
           }());
         }
         return widget;
       },
       childCount: _computeActualChildCount(itemCount),
       addAutomaticKeepAlives: addAutomaticKeepAlives,
       addRepaintBoundaries: addRepaintBoundaries,
       addSemanticIndexes: addSemanticIndexes,
       semanticIndexCallback: (Widget _, int index) {
         return index.isEven ? index ~/ 2 : null;
       },
     ),
     super(
       key: key,
       scrollDirection: scrollDirection,
       reverse: reverse,
       controller: controller,
       primary: primary,
       physics: physics,
       shrinkWrap: shrinkWrap,
       padding: padding,
       cacheExtent: cacheExtent,
       semanticChildCount: itemCount,
       dragStartBehavior: dragStartBehavior,
       keyboardDismissBehavior: keyboardDismissBehavior,
       restorationId: restorationId,
       clipBehavior: clipBehavior,
     );
     
     

>>> ListView.separated ์ฃผ์š” ์†์„ฑ

  • padding : children์„ ์‚ฝ์ž…ํ•  ๊ณต๊ฐ„ => final EdgeInsetsGeometry? padding;
  • scrollerDirection : ์Šคํฌ๋กค ๋ฐฉํ–ฅ ์„ค์ • ์†์„ฑ => final Axis scrollDirection;
  • itemBuilder : child๋“ค์„ ์–ด๋–ป๊ฒŒ ๋ฐฐ์น˜ํ•  ์ง€ ์ •ํ•˜๋Š” ์†์„ฑ => required IndexedWidgetBuilder itemBuilder
  • separatorBuilder : ๊ตฌ๋ถ„์ž๋ฅผ ์–ด๋–ป๊ฒŒ ๊ทธ๋ฆด์ง€ ์ •ํ•˜๋Š” ์†์„ฑ => required IndexedWidgetBuilder separatorBuilder
  • itemCount : child์˜ ๊ฐœ์ˆ˜ => required int itemCount

>>> 4. ListView.custom : ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ ๊ฐ€๋Šฅ

profile
์•ˆ๋‡ฝํฌ๋””

0๊ฐœ์˜ ๋Œ“๊ธ€