User Interaction – Dismissible

Masih menggunakan proyek shopping cart, pada kali ini kita akan menambahkan user interaksi dismissible.

Dismissible adalah widget yang berguna untuk membuang element yang dibungkus oleh widget Dismissible. Pada contoh, kita akan buang isi cart item dengan melakukan swipe dari kanan ke kiri.

Pertama kita buka file cart_content.dart, kita tambahkan widget Disimissible pada widget Card yang berisi informasi product. Property yang penting diperhatikan adalah:

  • key: yang biasanya diisi dengan ValueKey(). Parameter yang digunakan adalah variable id dari class.
  • direction: untuk mengatur arah swipe, pada contoh digunakan swipe dari kanan ke kiri (endtostart).
  • onDimissed: diisi dengan fungsi yang akan melakukan proses apa saja setelah didismissed. Pada contoh kita akan hapus product dari cart, dengan memanggil method removeCartProduct() yang kita buat di file cart_provider.dart

Parameter lainnya lebih ke styling. Untuk dokumentasi detail kunjungi https://api.flutter.dev/flutter/widgets/Dismissible-class.html

Widget build(BuildContext context) {
  return Dismissible(
    key: ValueKey(id),
    background: Container(
      color: Theme.of(context).errorColor,
      child: Icon(
        Icons.delete,
        color: Colors.white,
      ),
      alignment: Alignment.centerRight,
      margin: EdgeInsets.symmetric(horizontal: 5, vertical: 7),
    ),
    direction: DismissDirection.endToStart,
    onDismissed: (direction) {
      Provider.of<Cart>(context, listen: false).removeCartProduct(pid);
    },
    child: Card(

Masih pada file cart_content.dart, kita juga perlu lakukan modifikasi dengan import file pendukung.

import 'package:provider/provider.dart';
import '../models/cart_provider.dart';

Pada bagian constructor juga perlu ditambahkan parameter untuk mendapatkan value product id, pada contoh digunakan variable pid.

class CartContent extends StatelessWidget {
  final String id;
  final String pid;
  final String title;
  final int qty;
  final double prc;

  CartContent(this.id, this.pid, this.title, this.prc, this.qty);
//cart_content.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/cart_provider.dart';

class CartContent extends StatelessWidget {
  final String id;
  final String pid;
  final String title;
  final int qty;
  final double prc;

  CartContent(this.id, this.pid, this.title, this.prc, this.qty);

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: ValueKey(id),
      background: Container(
        color: Theme.of(context).errorColor,
        child: Icon(
          Icons.delete,
          color: Colors.white,
        ),
        alignment: Alignment.centerRight,
        padding: EdgeInsets.only(right: 20),
        margin: EdgeInsets.symmetric(horizontal: 5, vertical: 7),
      ),
      direction: DismissDirection.endToStart,
      onDismissed: (direction) {
        Provider.of<Cart>(context, listen: false).removeCartProduct(pid);
      },
      child: Card(
        margin: EdgeInsets.symmetric(horizontal: 5, vertical: 7),
        child: Padding(
          padding: EdgeInsets.all(8),
          child: ListTile(
            leading: CircleAvatar(child: FittedBox(child: Text('\$$prc'))),
            title: Text(title),
            subtitle: Text('Total: \$${prc * qty}'),
            trailing: Text('\$$qty x'),
          ),
        ),
      ),
    );
  }
}

Berikutnya, pada file cart_provider.dart, kita tambahkan method untuk menghapus product dari cart.

void removeCartProduct(pid) {
  _cartItem.remove(pid);
  notifyListeners();
}
//cart_provider.dart

import 'package:flutter/foundation.dart';

class CartItem {
  final String id;
  final String title;
  final double price;
  final int qty;

  CartItem({
    @required this.id,
    @required this.title,
    @required this.price,
    @required this.qty,
  });
}

class Cart with ChangeNotifier {
  Map<String, CartItem> _cartItem = {};

  Map<String, CartItem> get cartItem {
    return {..._cartItem};
  }

  int get totalItem {
    return _cartItem.length;
  }

  double get totalAmount {
    var total = 0.0;
    _cartItem.forEach((key, value) {
      total += value.price * value.qty;
    });
    return total;
  }

  void addItem(String pid, String title, double price) {
    if (_cartItem.containsKey(pid)) {
      _cartItem.update(
          pid,
          (ccart) => CartItem(
              id: ccart.id,
              title: ccart.title,
              price: ccart.price,
              qty: ccart.qty + 1));
    } else {
      _cartItem.putIfAbsent(
          pid,
          () => CartItem(
              id: DateTime.now().toString(),
              title: title,
              price: price,
              qty: 1));
    }
    notifyListeners();
  }

  void undoAddProd(String pid) {
    if (!_cartItem.containsKey(pid)) {
      return;
    }
    if (_cartItem[pid].qty <= 1) {
      _cartItem.remove(pid);
    } else {
      _cartItem.update(
          pid,
          (crt) => CartItem(
              id: crt.id,
              title: crt.title,
              price: crt.price,
              qty: crt.qty - 1));
    }
    notifyListeners();
  }

  void removeCartProduct(pid) {
    _cartItem.remove(pid);
    notifyListeners();
  }
}

Terakhir, jangan lupa untuk mengubah file cart_scr.dart, karena pada file cart_content.dart kita ubah constructornya untuk menerima parameter product id.

Product id dapat diakses dengan perintah cartCnt.cartItem.keys.toList()[i]. Ingat cartItem adalah object Map<String, CartItem>, dimana String adalah productId.

  itemBuilder: (ctx, i) => CartContent(
      cartCnt.cartItem.values.toList()[i].id,
      cartCnt.cartItem.keys.toList()[i],
      cartCnt.cartItem.values.toList()[i].title,
      cartCnt.cartItem.values.toList()[i].price,
      cartCnt.cartItem.values.toList()[i].qty),
),
// cart_scr.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/cart_provider.dart';
import './cart_content.dart';

class CartSccr extends StatelessWidget {
  static const routeNm = '/cart';

  @override
  Widget build(BuildContext context) {
    final cartCnt = Provider.of<Cart>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Your Cart'),
      ),
      body: Column(
        children: <Widget>[
          Card(
            margin: EdgeInsets.all(8),
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(
                    'Total',
                    style: TextStyle(
                      fontSize: 18,
                    ),
                  ),
                  Spacer(),
                  Chip(
                    label: Text(
                      '\$${cartCnt.totalAmount}',
                      style: TextStyle(color: Colors.white),
                    ),
                    backgroundColor: Theme.of(context).primaryColor,
                  ),
                  FlatButton(
                    onPressed: null,
                    child: Text('Order Now'),
                    textColor: Theme.of(context).primaryColor,
                  ),
                ],
              ),
            ),
          ),
          SizedBox(height: 10),
          Expanded(
            child: ListView.builder(
              itemCount: cartCnt.cartItem.length,
              itemBuilder: (ctx, i) => CartContent(
                  cartCnt.cartItem.values.toList()[i].id,
                  cartCnt.cartItem.keys.toList()[i],
                  cartCnt.cartItem.values.toList()[i].title,
                  cartCnt.cartItem.values.toList()[i].price,
                  cartCnt.cartItem.values.toList()[i].qty),
            ),
          ),
        ],
      ),
    );
  }
}
Sharing is caring:

Leave a Comment