Flutter untuk iOS-Menambahkan Item

Setiap tahun kami mencoba menyempurnakan makan malam kami di hari Natal, tahun ini fokusnya adalah pada pemanggangan yang lebih baik.

Mari kita lihat bagaimana kita dapat menemukan dan menambahkan resep kentang panggang baru ke dalam intisari kita.

Penerimaan terhadap persyaratan ini adalah mampu:

  • Cari resep baru
  • Simpan ke intisari kami:
  • Judul
  • Pengarang
  • Gambar kecil

Untuk memulai saya menambahkan bilah navigasi atas dengan tindakan yang memungkinkan kita menambahkan resep.

@override
Widget build(BuildContext context) {
  return CupertinoPageScaffold(
    navigationBar: const CupertinoNavigationBar(
      heroTag: "RecipeTabHeroTag",
      transitionBetweenRoutes: false,
      middle: Text(
        "Recipies",
      ),
      trailing: Icon(CupertinoIcons.add)
    ),
    child: Container(
      color: CupertinoColors.activeGreen,
      child: recipiesList(),
    ),
  );
}

Saya mengganti nama tab kembali menjadi 'Intisari' sekarang kami memiliki judul 'Resep' di bilah navigasi atas.

Sekarang untuk keputusan cepat lainnya kita akan menggeser layar ke atas ketika tombol tambah diklik dan menampilkan bilah pencarian untuk memungkinkan kita menemukan resep baru.

Dengan demikian, kita hanya perlu memanfaatkan pencarian Google untuk menemukan beberapa resep baru.

Saya membuka SerpAPI untuk ini dan mengambil beberapa data dari penelusuran resep kentang panggang dengan cuka balsamic.

https://serpapi.com/search.json?q=Roast+potatoes+with+balsamic&location=United+Kingdom&hl=en&gl=uk&google_domain=google.co.uk&api_key=secret_api_key

{
    "search_metadata": {
      "id": "61c3369cc99903747c1e643b",
      "status": "Success",
      "json_endpoint": "https://serpapi.com/searches/bdb5db8a7f4c5593/61c3369cc99903747c1e643b.json",
      "created_at": "2021-12-22 14:30:52 UTC",
      "processed_at": "2021-12-22 14:30:52 UTC",
      "google_url": "https://www.google.co.uk/search?q=Roast+potatoes+with+balsamic&oq=Roast+potatoes+with+balsamic&uule=w+CAIQICIOVW5pdGVkIEtpbmdkb20&hl=en&gl=uk&sourceid=chrome&ie=UTF-8",
      "raw_html_file": "https://serpapi.com/searches/bdb5db8a7f4c5593/61c3369cc99903747c1e643b.html",
      "total_time_taken": 1.99
    },
    "search_parameters": {
      "engine": "google",
      "q": "Roast potatoes with balsamic",
      "location_requested": "United Kingdom",
      "location_used": "United Kingdom",
      "google_domain": "google.co.uk",
      "hl": "en",
      "gl": "uk",
      "device": "desktop"
    },
    "search_information": {
      "organic_results_state": "Results for exact spelling",
      "query_displayed": "Roast potatoes with balsamic",
      "total_results": 12800000,
      "time_taken_displayed": 0.49
    },
    "recipes_results": [
      {
        "title": "Balsamic potatoes",
        "link": "https://www.jamieoliver.com/recipes/potato-recipes/balsamic-potatoes/",
        "source": "Jamie Oliver",
        "total_time": "2 hrs 20 mins",
        "ingredients":
        [
          "Balsamic vinegar",
          "maris piper potatoes",
          "red onions",
          "rocket",
          "olive oil"
        ],
        "thumbnail": "https://serpapi.com/searches/61c3369cc99903747c1e643b/images/bd928f9ef521c02bbdb2df96157011d6a02d619d06f8a6e0e62bb157f48e10e5.jpeg"
      },
      {
        "title": "Balsamic roast potatoes",
        "link": "https://www.taste.com.au/recipes/balsamic-roast-potatoes/1bcb6bd4-2efa-4f01-bc98-f2ce32eaa906",
        "source": "Taste",
        "rating": 4,
        "reviews": 2,
        "total_time": "1 hr 5 mins",
        "ingredients":
        [
          "Balsamic vinegar",
          "kipfler potatoes",
          "olive oil",
          "garlic"
        ],
        "thumbnail": "https://serpapi.com/searches/61c3369cc99903747c1e643b/images/bd928f9ef521c02bbdb2df96157011d625322c9b727d95f76706f0471bbaba31.jpeg"
      },
      {
        "title": "Balsamic roast potatoes",
        "link": "https://www.delicious.com.au/recipes/balsamic-roast-potatoes/1e2f30ad-d9b4-41bf-aa2e-16f1e2accfb7",
        "source": "Delicious",
        "rating": 5,
        "reviews": 1,
        "total_time": "1 hr 5 mins",
        "ingredients":
        [
          "Balsamic vinegar",
          "kipfler potatoes",
          "olive oil",
          "garlic"
        ],
        "thumbnail": "https://serpapi.com/searches/61c3369cc99903747c1e643b/images/bd928f9ef521c02bbdb2df96157011d6ebca3a2868589cb9feab32215a0ba5e8.jpeg"
      }
    ]
}

Menambahkan daftar untuk mengembalikan hasil pencarian.

Ketika hasilnya dipilih (onTap) kami menambahkannya ke intisari resep kami.

Ta Da

Pembakar Belakang

Menyimpan intisari.

Untuk saat ini kami menyimpan resep yang ditambahkan di memori, nanti kami dapat menyimpannya secara lokal dan jarak jauh ke penyimpanan data kami.

Khusus iOS — Klik tab untuk mengatur ulang

Menambahkan fungsionalitas untuk menavigasi kembali ke tingkat/status teratas saat mengetuk item tab saat ini, ini adalah pengalaman iOS yang bagus, desain yang diharapkan orang.

Bilah Pencarian Animasi

Saya memutuskan untuk menghindari penerapan bilah pencarian lebih lanjut yang serupa dengan yang ada di aplikasi "App Store" Apple yang memiliki fokus animasi.

Kita dapat melihat ini dan mencoba meningkatkan bilah pencarian nanti setelah dasar-dasarnya sudah siap.

Bidang Teks Pencarian Cupertino

Saya mendapatkan beberapa kesalahan tingkat perpustakaan dari Flutter yang meminta saya untuk melaporkan bug kerangka kerja ketika menekan enter pada keyboard di bidang pencarian menggunakan emulator iOS.

Untuk saat ini saya telah mengabstraksikannya ke dalam widget dan bermaksud menggantinya dengan versi khusus yang memiliki lebih banyak fitur.

Saya juga memperhatikan bahwa Anda harus memasukkan dua kali pada keyboard di emulator sebelum acara 'OnTap' diaktifkan.

XP

Dalam data memori

Kita perlu menyimpan dan memelihara daftar resep agar kita dapat menambahkan resep baru.

Pada titik ini kami menggunakan kelas repositori memori untuk mengelolanya dan memasukkannya sebagai ChangeNotifierProvider.

ChangeNotifierProvider<MemoryRepository>(
	create: (_) => MemoryRepository(),
    lazy: false,
),

Kedengarannya rumit tapi itu hanya daftar resep di memori dan beberapa metode untuk menambah dan mengambilnya.

List<Recipe> findAllRecipes();
Recipe addRecipe(Recipe recipe);

Lihat dokumentasi Flutter untuk informasi selengkapnya tentang pengelolaan status.

Saat kita pindah ke penyimpanan data, mis. DB melalui API kita dapat meningkatkan kode ini.

Daftar Item Digunakan Kembali

Sebagai bagian dari menampilkan hasil pencarian kita perlu menampilkan daftar lagi, jadi saya mengabstraksi item daftar intisari awal sehingga kita dapat menggunakannya kembali dan memastikan item daftar kita memiliki tampilan dan nuansa yang sama di seluruh aplikasi.

Widget recipesList() {
  final repository = Provider.of<MemoryRepository>(context);
  var recipes = repository.findAllRecipes();

  return ListView.builder(
    itemCount: recipes.length,
    itemBuilder: (context, index) {
      var listItemInfo = ListItemInfo(
        id: recipes[index].link,
        author: recipes[index].source,
        title: recipes[index].title,
        titleImage: Image.network(recipes[index].thumbnail),
        showAddIcon: false,
      );

      return ListItem(listItemInfo);
    },
  );
}

Widget recipeSearchResultsList() {
  var searchResultRecipes = _searchResults.data.length > 0
    ? Recipe.fromSerpApiResultJson(_searchResults.data)
    : <Recipe>[];

  final repository = Provider.of<MemoryRepository>(context);

  return ListView.builder(
    itemCount: searchResultRecipes.length,
    itemBuilder: (context, index) {
      var listItemInfo = ListItemInfo(
        id: searchResultRecipes[index].link,
        author: searchResultRecipes[index].source,
        title: searchResultRecipes[index].title,
        titleImage: Image.network(searchResultRecipes[index].thumbnail),
        showAddIcon: true,
        onTap: () => {
          repository.addRecipe(searchResultRecipes[index]),
          Navigator.pop(context)
        },
      );

      return ListItem(listItemInfo);
    },
  );
}

Scope Creep (Hati-hati — YUTNI Kemungkinan besar Anda tidak membutuhkannya)

Bagi saya ini adalah waktu yang paling menggoda untuk mencoba merekayasa proyek secara berlebihan karena masih ada beberapa hal penting yang hilang.

Saya ingin melakukan lebih banyak pekerjaan pada:

  • akses data, termasuk permintaan api batch
  • desain widget yang jauh lebih baik dengan animasi yang bagus
  • menambahkan tema dan rasa
  • pencatatan
  • Pengujian penerimaan otomatis.
  • Tingkatkan desain untuk Android
  • Lihatlah cara kerjanya sebagai situs web
  • membawa beberapa perpustakaan manajemen negara
  • dll..

Namun pengalaman memberitahu saya untuk menahan keinginan untuk menyimpang, bahkan beberapa penelitian awal di Google, telah memperlambat posting ini secara signifikan.

Pada akhirnya saya kembali ke mentalitas demo untuk membuatnya berfungsi, diimbangi dengan saran dari Paman Bob, bahwa jika berhasil hanya 50%, Anda sekarang harus melakukannya dengan benar.

Itu setara dengan lebih banyak waktu mengekstraksi metode dan merapikannya.

Selama kita memberikan setiap kelas, metode satu tanggung jawab dalam filenya sendiri, kita dapat dengan mudah memperbaikinya secara mandiri nanti, saat kita beralih dari konsep ke siap produksi.

Seringkali scope creep muncul ketika saya bosan dengan disiplin tugas yang ada karena disiplin terasa lambat.

Tautan

Terima kasih banyak kepada M4trix Dev karena artikelnya di iOS Tab Bar sangat berharga dan memungkinkan saya dengan cepat memperbaiki masalah yang saya alami pada implementasi pertama saya.

Rakyat

“Masalahnya adalah, sangat mudah untuk menjadi berbeda, namun sangat sulit untuk menjadi lebih baik.”

Jony Ive_

Suara & Penglihatan

Satu hal lagi

“Saya bercermin setiap pagi dan bertanya pada diri sendiri: “Jika hari ini adalah hari terakhir dalam hidup saya, apakah saya ingin melakukan apa yang akan saya lakukan hari ini?” Dan setiap kali jawabannya “Tidak” selama beberapa hari berturut-turut, saya tahu saya perlu mengubah sesuatu.”

Steve Jobs_