菜逼八寫Flutter(3) - 列表、圖片Widget


Posted by TempuraEngineer on 2022-10-24

目錄


ListView

用於展示多筆資料的列表,可滑動。會一次建立完整個列表,如果沒配合builder()可能造成App閃退

// 寫在class _MyHomePageState裡
final List<int> colorCodes = <int>[600, 500, 400, 300, 200, 100];

Expanded(
  child: ListView.separated( // 建立一個「資料長度固定的」可滑動list,並用線隔開,但加分隔線還是要寫在separatorBuilder
    padding:
        const EdgeInsets.symmetric(horizontal: 8), // 水平方向的padding
    itemCount: colorCodes.length,
    itemBuilder: (BuildContext context, int index) { // 類似vue v-for
      return Container(
        height: 150,
        color: Colors.amber[colorCodes[index]],
        child: Center(child: Text('黃色${colorCodes[index]}')),
      );
    },
    separatorBuilder: (BuildContext context, int index) =>
        const Divider(color: Colors.black26, thickness: 2),
  ),
)

ListView.builder則是滑到哪建到哪,可以用在撈資料的時候,做infinite scroll

Creates a scrollable, linear array of widgets that are created on demand.
This constructor is appropriate for list views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.


Image

用於展示圖片,分為5種,下面只列最常用的2種

  • Image.asset
    圖片在assets資料夾裡

    Image.asset(
      'assets/images/logo.png',
      height: 100,
      fit: BoxFit.cover, // 類似css background-size:cover
    ),
    
  • Image.network & NetworkImage
    圖片在網路上

    Image.network()比較陽春,是NetworkImage的shorthand。沒有loading完淡入圖片快取圖片的功能

    Image.network('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg')
    

    NetworkImage則不論header設甚麼,都會快取圖片

    NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg')
    

透過builder可以自訂圖片不同階段的樣式

  • loadingBuilder & errorBuilder

    loading時、載入錯誤時的樣式`

  Image.network(
    'https://images.unsplash.com/photo-1471899236350-e3016bf1e69e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=871&q=80',
    errorBuilder:(BuildContext context, Object object, StackTrace? trace) =>
      Center(
        child: Text(
          'loading image failed',
          style:
              TextStyle(fontSize: 32, color: Colors.red.shade400),
        ),
    ),
    loadingBuilder: (BuildContext context, Widget child,
        ImageChunkEvent? loadingProgress) {
      if (loadingProgress == null) return child;

      return Shimmer.fromColors(
          baseColor: Colors.grey.shade300,
          highlightColor: Colors.grey.shade100,
          child: Expanded(
            child: Container(
              height: 250,
              color: Colors.white,
            ),
          ));
    },
  )
  • frameBuilder
    圖片淡入效果。和loadingBuilder同時存在時,frameBuilder的res會被當作參數傳給loadingBuilder

  Image.network(
    'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',
    frameBuilder: (context, child, frame, wasSync) {
    if (wasSync) return child;

    return AnimatedOpacity(
      child: child,
      opacity: frame == null ? 0 : 1,
      duration: const Duration(seconds: 3),
      curve: Curves.easeOut,
    );
  })


Shimmer

用於圖片loading時shimmer樣式的package

import 'package:shimmer/shimmer.dart';

SizedBox(
  width: 200,
  height: 100,
  child: Shimmer.fromColors(
    baseColor: Colors.blue,
    highlightColor: Colors.yellow,
    child: Text(
      'image is loading now',
      textAlign: TextAlign.center,
      style: TextStyle(
        fontSize: 40,
        fontWeight:
        FontWeight.bold,
      ),
    ),
  ),
);


參考資料

Display images from the internet
Check image is loaded in Image.network widget


#Flutter #listview #image







Related Posts

如何充滿熱情地學習 - 以資料結構為例

如何充滿熱情地學習 - 以資料結構為例

W11_怎麼做一個 Blog

W11_怎麼做一個 Blog

Day 68 - Authentication & Flask Login & Werkzeug

Day 68 - Authentication & Flask Login & Werkzeug


Comments