web analytics

Flutter : เลือกรูปภาพจาก Gallery

สวัสดีครับ ผู้อ่านครับ วันนี้ว่างๆลองหาอะไรเล่นใน Flutter ก็เจอ library สำหรับทำ multi image picker ช่วยในการเปิด gallery แล้วเลือกรูปภาพมาใช้ในแอปของเรา ซึ่งเท่าที่ผมดูมาหลายตัว พบว่าตัวนี้ค่อนข้างดูดี เพราะว่าเลือกใช้ library ที่ได้รับความนิยมอยู่แล้วจาก native อีกที ทำให้ได้ UX ที่เหมาะสมกับ platform นั้น

อ่าน doc ของเขาได้ที่นี่ ทำไว้ดีทีเดียวนะ
https://sh1d0w.github.io/multi_image_picker/

เริ่มต้น

หากโปรเจคเรามี android library ที่ใช้ AndroidX ให้ใช้ package เวอชัน 4.x แต่ถ้าไม่ใช้ก็ใช้ 2.x โปรเจคนี้ผม migrate มาใช้ androidx แล้ว เลยใช้ 4.x

dependencies:
  multi_image_picker: ^4.1.2

สำหรับการ Migrate มาใช้ androidx อ่านได้ที่ลิงค์ด้านล่างนี้เลย

เพิ่ม permission

ใน android เพิ่ม permission นี้ ที่ android/src/main/AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

แล้วก็ที่ android/app/build.gradle
เปลี่ยน minSdkVersion เป็น 19

android {
    ..

    defaultConfig {
        minSdkVersion 19

สำหรับ iOS เพิ่มที่ Info.plist

<key>NSPhotoLibraryUsageDescription</key>
<string>Example usage description</string>
<key>NSCameraUsageDescription</key>
<string>Example usage description</string>

การใช้งาน

มาลองเล่นกัน ก่อนอื่นก็ import เข้ามาที่ main.dart

import 'package:multi_image_picker/multi_image_picker.dart';

ประกาศ List<Asset> อันนี้เป็น class ของ library ที่ทำการ map ตัว asset object ของแต่ละ platform มาให้เป็น Asset

class _MyImagesPageState extends State<MyHomePage> {
  List<Asset> images = List<Asset>();

ใส่ method สำหรับเปิดหน้าจอเลือกรูปภาพ และหลังจากเลือกแล้วก็จะได้ List<Asset> นั่นเอง เราก็เอาไปเก็บไว้ในตัวแปรที่เตรียมไว้ จากนั้นเรียก setState

  Future<void> loadAssets() async {
    setState(() {
      images = List<Asset>();
    });
    List<Asset> resultList;
    String error;

    try {
      resultList = await MultiImagePicker.pickImages(
        maxImages: 300,
      );
    } catch (e) {}

    if (!mounted) return;

    setState(() {
      images = resultList;
    });
  }

ทำส่วนเลือกรูปภาพแล้ว แต่ยังไม่ได้ทำปุ่มให้กดแล้วเปิดหน้าจอขึ้นมา ในตัวอย่างนี้ผมเพิ่ม action เป็นไอคอนไว้มุมขวา

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.camera_alt),
              onPressed: () async {
                await loadAssets();
              })
        ],
      )

ได้แบบนี้ ซึ่งพอกดปล้วจะเรียก loadAsset() นั่นเอง

จากนั้นแอปจะถามหา permission ส่วนนี้ library จัดการให้เรียบร้อย ไม่ต้องเขียนเช็ค permission เลย

สิ่งที่ได้คือ หน้าจอ gallery สำหรับเลือกรูปภาพ

สามารถเลือกรูปได้ตาม max ที่เรากำหนดไว้

แต่ว่า เรายังไม่ได้ทำส่วนสำหรับเลือกรูปภาพแล้วนำมาแสดงในแอปของเราเลย ดังนั้นเลยต้องเพิ่ม GridView สำหรับแสดงรูปภาพ

GridView.builder(itemCount: images.length,
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(childAspectRatio: 1.3, maxCrossAxisExtent: 300),
            itemBuilder: (context, i) {
          return AssetThumb(
              asset: images[i],
              height: 300,
              width: MediaQuery.of(context).size.width.toInt());
        })

หลังจากเราเลือกรูปภาพแล้ว รูปเหล่านั้นก็จะเอามาใส่ใน GridView แล้วละ

ที่เหลือ เรายังสามารถตกแต่งหน้า gallery ที่เลือกรูปภาพได้ด้วย เช่นใน android ก็กำหนดที่ materialOptions ใส่สี ActionBar สีตัวหนังสือ

resultList = await MultiImagePicker.pickImages(
        maxImages: 10,
        materialOptions:MaterialOptions(
          actionBarTitle: "Select picture",
          allViewTitle: "All",
          actionBarColor: "#9b59b6",
          actionBarTitleColor: "#ffffff",
          lightStatusBar: false,
          statusBarColor: '#8e44ad',
          startInAllView: true,
          selectCircleStrokeColor: "#34495e",
        )
      );

ได้แล้ว