فلوتر MDC-102: ساختار و چیدمان مواد

1. مقدمه

logo_components_color_2x_web_96dp.png

Material Components (MDC) به توسعه دهندگان کمک می کند طراحی مواد را پیاده سازی کنند. MDC که توسط تیمی از مهندسان و طراحان UX در Google ایجاد شده است، دارای ده‌ها مؤلفه رابط کاربری زیبا و کاربردی است و برای Android، iOS، وب و Flutter.material.io/develop در دسترس است.

در Codelab MDC-101 ، از دو مؤلفه مواد برای ساختن صفحه ورود استفاده کردید: فیلدهای متنی و دکمه‌هایی با امواج جوهر. اکنون اجازه دهید این پایه را با افزودن ناوبری، ساختار و داده ها گسترش دهیم.

چیزی که خواهی ساخت

در این کد لبه، شما یک صفحه اصلی برای اپلیکیشنی به نام Shrine می سازید، یک اپلیکیشن تجارت الکترونیک که پوشاک و کالاهای خانگی را می فروشد. شامل موارد زیر خواهد بود:

  • نوار برنامه برتر
  • یک لیست شبکه ای پر از محصولات

اندروید

iOS

برنامه تجارت الکترونیک با نوار برنامه برتر و شبکه ای پر از محصولات

برنامه تجارت الکترونیک با نوار برنامه برتر و شبکه ای پر از محصولات

اجزاء و زیرسیستم های Flutter مواد در این آزمایشگاه کد

  • نوار برنامه بالا
  • شبکه ها
  • کارت ها

سطح تجربه خود را با توسعه فلاتر چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

2. محیط توسعه Flutter خود را تنظیم کنید

برای تکمیل این آزمایشگاه به دو نرم افزار نیاز دارید - Flutter SDK و یک ویرایشگر .

شما می توانید کدلب را با استفاده از هر یک از این دستگاه ها اجرا کنید:

  • یک دستگاه فیزیکی Android یا iOS که به رایانه شما متصل شده و روی حالت Developer تنظیم شده است.
  • شبیه ساز iOS (نیاز به نصب ابزار Xcode دارد).
  • شبیه ساز اندروید (نیاز به نصب در Android Studio دارد).
  • یک مرورگر (Chrome برای اشکال زدایی لازم است).
  • به عنوان یک برنامه دسکتاپ Windows ، Linux ، یا macOS . شما باید روی پلتفرمی که قصد استقرار در آن را دارید توسعه دهید. بنابراین، اگر می خواهید یک برنامه دسکتاپ ویندوز توسعه دهید، باید در ویندوز توسعه دهید تا به زنجیره ساخت مناسب دسترسی داشته باشید. الزامات خاص سیستم عامل وجود دارد که به طور مفصل در docs.flutter.dev/desktop پوشش داده شده است.

3. برنامه استارتر Codelab را دانلود کنید

از MDC-101 ادامه می دهید؟

اگر MDC-101 را تکمیل کرده اید، کد شما باید برای این کد لبه آماده شود. رفتن به مرحله: یک نوار برنامه برتر اضافه کنید .

از صفر شروع کنم؟

برنامه codelab starter را دانلود کنید

برنامه شروع در فهرست راهنمای material-components-flutter-codelabs-102-starter_and_101-complete/mdc_100_series قرار دارد.

... یا آن را از GitHub شبیه سازی کنید

برای شبیه سازی این کد لبه از GitHub، دستورات زیر را اجرا کنید:

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd material-components-flutter-codelabs/mdc_100_series
git checkout 102-starter_and_101-complete

پروژه را باز کنید و برنامه را اجرا کنید

  1. پروژه را در ویرایشگر انتخابی خود باز کنید.
  2. دستورالعمل‌های «اجرای برنامه» را در Get Started: Test Drive برای ویرایشگر انتخابی خود دنبال کنید.

موفقیت! شما باید صفحه ورود به حرم را از آزمایشگاه کد MDC-101 در دستگاه خود ببینید.

اندروید

iOS

صفحه ورود با فیلدهای نام کاربری و رمز عبور، دکمه های لغو و بعدی

صفحه ورود با فیلدهای نام کاربری و رمز عبور، دکمه های لغو و بعدی

اکنون که صفحه ورود به سیستم خوب به نظر می رسد، بیایید برنامه را با برخی از محصولات پر کنیم.

4. یک نوار برنامه برتر اضافه کنید

در حال حاضر، اگر روی دکمه "بعدی" کلیک کنید، می توانید صفحه اصلی را مشاهده کنید که می گوید "شما آن را انجام دادید!". این عالی است! اما اکنون کاربر ما هیچ اقدامی برای انجام دادن ندارد، یا هیچ حسی از جایی که در برنامه است ندارد. برای کمک، زمان اضافه کردن ناوبری است.

طراحی متریال الگوهای ناوبری را ارائه می دهد که درجه بالایی از قابلیت استفاده را تضمین می کند. یکی از قابل مشاهده ترین مولفه ها، نوار بالای برنامه است.

برای ارائه ناوبری و دسترسی سریع کاربران به سایر اقدامات، بیایید یک نوار برنامه برتر اضافه کنیم.

ویجت AppBar را اضافه کنید

در home.dart ، یک AppBar را به Scaffold اضافه کنید و const برجسته شده را حذف کنید:

return const Scaffold(
  // TODO: Add app bar (102)
  appBar: AppBar(
    // TODO: Add buttons and title (102)
  ),

افزودن AppBar به فیلد Scaffold's appBar: یک چیدمان کامل را به صورت رایگان به ما می دهد و AppBar را در بالای صفحه و بدنه زیر آن نگه می دارد.

یک ویجت متن اضافه کنید

در home.dart ، عنوانی را به AppBar اضافه کنید:

// TODO: Add app bar (102)
  appBar: AppBar(
    // TODO: Add buttons and title (102)
    title: const Text('SHRINE'),
    // TODO: Add trailing buttons (102)

پروژه خود را ذخیره کنید

اندروید

iOS

نوار برنامه با عنوان Shrine

نوار برنامه با عنوان Shrine

بسیاری از نوارهای برنامه یک دکمه در کنار عنوان دارند. بیایید یک نماد منو در برنامه خود اضافه کنیم.

یک IconButton پیشرو اضافه کنید

در حالی که هنوز در home.dart هستید، یک IconButton برای قسمت leading: تنظیم کنید. (آن را قبل از title: فیلد برای تقلید از ترتیب اول به آخر قرار دهید):

    // TODO: Add buttons and title (102)
    leading: IconButton(
      icon: const Icon(
        Icons.menu,
        semanticLabel: 'menu',
      ),
      onPressed: () {
        print('Menu button');
      },
    ),

پروژه خود را ذخیره کنید

اندروید

iOS

نوار برنامه با عنوان Shrine و نماد منوی همبرگر

نوار برنامه با عنوان Shrine و نماد منوی همبرگر

نماد منو (همچنین به عنوان "همبرگر" شناخته می شود) درست در جایی که انتظارش را دارید نشان داده می شود.

همچنین می توانید دکمه هایی را به سمت انتهایی عنوان اضافه کنید. در فلوتر به اینها «اکشن» می گویند.

اعمال را اضافه کنید

جا برای دو دکمه آیکون دیگر وجود دارد.

آنها را پس از عنوان به نمونه AppBar اضافه کنید:

// TODO: Add trailing buttons (102)
actions: <Widget>[
  IconButton(
    icon: const Icon(
      Icons.search,
      semanticLabel: 'search',
    ),
    onPressed: () {
      print('Search button');
    },
  ),
  IconButton(
    icon: const Icon(
      Icons.tune,
      semanticLabel: 'filter',
    ),
    onPressed: () {
      print('Filter button');
    },
  ),
],

پروژه خود را ذخیره کنید صفحه اصلی شما باید به شکل زیر باشد:

اندروید

iOS

نوار برنامه با عنوان Shrine و نماد منوی همبرگر و جستجوی دنباله دار و نمادهای سفارشی سازی

نوار برنامه با عنوان Shrine و نماد منوی همبرگر و جستجوی دنباله دار و نمادهای سفارشی سازی

اکنون برنامه دارای یک دکمه پیشرو، یک عنوان و دو عمل در سمت راست است. نوار برنامه همچنین ارتفاع را با استفاده از یک سایه ظریف نشان می دهد که نشان می دهد در لایه ای متفاوت از محتوا قرار دارد.

5. یک کارت را در یک شبکه اضافه کنید

اکنون که برنامه ما ساختاری دارد، بیایید محتوا را با قرار دادن آن در کارت ها سازماندهی کنیم.

یک GridView اضافه کنید

بیایید با اضافه کردن یک کارت در زیر نوار بالای برنامه شروع کنیم. ویجت Card به تنهایی اطلاعات کافی برای قرار دادن جایی که می‌توانیم آن را ببینیم ندارد، بنابراین می‌خواهیم آن را در یک ویجت GridView قرار دهیم.

مرکز موجود در بدنه داربست را با GridView جایگزین کنید:

// TODO: Add a grid view (102)
body: GridView.count(
  crossAxisCount: 2,
  padding: const EdgeInsets.all(16.0),
  childAspectRatio: 8.0 / 9.0,
  // TODO: Build a grid of cards (102)
  children: <Widget>[Card()],
),

بیایید آن کد را باز کنیم. GridView سازنده count() فراخوانی می کند زیرا تعداد آیتم هایی که نمایش می دهد قابل شمارش است و بی نهایت نیست. اما برای تعریف چیدمان به اطلاعات بیشتری نیاز دارد.

crossAxisCount: تعداد آیتم ها را مشخص می کند. ما 2 ستون می خواهیم.

فیلد padding: فضا را در هر 4 طرف GridView فراهم می کند. البته شما نمی‌توانید بالشتک‌ها را در قسمت‌های انتهایی یا انتهایی ببینید، زیرا هنوز هیچ کودک GridView در کنار آنها وجود ندارد.

فیلد childAspectRatio: اندازه آیتم ها را بر اساس نسبت ابعاد (عرض به ارتفاع) مشخص می کند.

به‌طور پیش‌فرض، GridView کاشی‌هایی را می‌سازد که همه اندازه‌شان یکسان است.

ما یک کارت داریم اما خالی است. بیایید ویجت های فرزند را به کارت خود اضافه کنیم.

چیدمان مطالب

کارت ها باید دارای مناطقی برای تصویر، عنوان و متن فرعی باشند.

فرزندان GridView را به روز کنید:

// TODO: Build a grid of cards (102)
children: <Widget>[
  Card(
    clipBehavior: Clip.antiAlias,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        AspectRatio(
          aspectRatio: 18.0 / 11.0,
          child: Image.asset('assets/diamond.png'),
        ),
        Padding(
          padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text('Title'),
              const SizedBox(height: 8.0),
              Text('Secondary Text'),
            ],
          ),
        ),
      ],
    ),
  )
],

این کد یک ویجت ستونی را اضافه می کند که برای چیدمان ویجت های فرزند به صورت عمودی استفاده می شود.

crossAxisAlignment: field CrossAxisAlignment.start را مشخص می‌کند که به معنای "تراز کردن متن با لبه اول" است.

ویجت AspectRatio تصمیم می گیرد که تصویر چه شکلی به خود بگیرد صرف نظر از نوع تصویر ارائه شده.

Padding متن را کمی از کنار می آورد.

دو ویجت متن به صورت عمودی با 8 نقطه فضای خالی بین آنها ( SizedBox ) انباشته شده اند. ما یک ستون دیگر می سازیم تا آنها را در داخل Padding قرار دهیم.

پروژه خود را ذخیره کنید

اندروید

iOS

یک مورد واحد با یک تصویر، عنوان و متن ثانویه

یک مورد واحد با یک تصویر، عنوان و متن ثانویه

در این پیش‌نمایش، می‌توانید ببینید که کارت از لبه، با گوشه‌های گرد، و یک سایه (که ارتفاع کارت را بیان می‌کند) قرار گرفته است. کل شکل را در Material "ظرف" می نامند. (با کلاس ویجت واقعی به نام Container اشتباه گرفته نشود.)

کارت ها معمولا در یک مجموعه با کارت های دیگر نشان داده می شوند. بیایید آنها را به عنوان یک مجموعه در یک شبکه قرار دهیم.

6. یک مجموعه کارت درست کنید

هر زمان که چندین کارت در یک صفحه وجود دارد، آنها با هم در یک یا چند مجموعه گروه بندی می شوند. کارت‌های یک مجموعه همسطح هستند، به این معنی که کارت‌ها دارای ارتفاع استراحت یکسانی با یکدیگر هستند (مگر اینکه کارت‌ها برداشته یا کشیده شوند، اما ما در اینجا این کار را انجام نمی‌دهیم).

کارت را در یک مجموعه ضرب کنید

در حال حاضر کارت ما به صورت خطی children: فیلدهای GridView ساخته شده است. این تعداد زیادی کد تو در تو است که خواندن آنها سخت است. بیایید آن را در تابعی استخراج کنیم که بتواند هر تعداد کارت خالی تولید کند و لیستی از کارت ها را برگرداند.

یک تابع خصوصی جدید بالای تابع build() بسازید (به یاد داشته باشید که توابعی که با خط زیر شروع می شوند API خصوصی هستند):

// TODO: Make a collection of cards (102)
List<Card> _buildGridCards(int count) {
  List<Card> cards = List.generate(
    count,
    (int index) {
      return Card(
        clipBehavior: Clip.antiAlias,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            AspectRatio(
              aspectRatio: 18.0 / 11.0,
              child: Image.asset('assets/diamond.png'),
            ),
            Padding(
              padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: const <Widget>[
                  Text('Title'),
                  SizedBox(height: 8.0),
                  Text('Secondary Text'),
                ],
              ),
            ),
          ],
        ),
      );
    },
  );
  return cards;
}

کارت های تولید شده را به فیلد children GridView اختصاص دهید. به یاد داشته باشید که همه موارد موجود در GridView را با این کد جدید جایگزین کنید :

// TODO: Add a grid view (102)
body: GridView.count(
  crossAxisCount: 2,
  padding: const EdgeInsets.all(16.0),
  childAspectRatio: 8.0 / 9.0,
  children: _buildGridCards(10) // Replace
),

پروژه خود را ذخیره کنید

اندروید

iOS

شبکه ای از آیتم ها با تصویر، عنوان و متن فرعی

شبکه ای از آیتم ها با تصویر، عنوان و متن فرعی

کارت ها وجود دارد، اما هنوز چیزی نشان نمی دهند. اکنون زمان اضافه کردن اطلاعات محصول است.

داده های محصول را اضافه کنید

این برنامه دارای برخی از محصولات با تصاویر، نام و قیمت است. بیایید آن را به ویجت هایی که قبلاً در کارت داریم اضافه کنیم

سپس، در home.dart ، یک بسته جدید و چند فایلی که برای مدل داده ارائه کرده ایم وارد کنید:

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

import 'model/product.dart';
import 'model/products_repository.dart';

در نهایت، _buildGridCards() را برای دریافت اطلاعات محصول تغییر دهید و از آن داده ها در کارت ها استفاده کنید:

// TODO: Make a collection of cards (102)

// Replace this entire method
List<Card> _buildGridCards(BuildContext context) {
  List<Product> products = ProductsRepository.loadProducts(Category.all);

  if (products.isEmpty) {
    return const <Card>[];
  }

  final ThemeData theme = Theme.of(context);
  final NumberFormat formatter = NumberFormat.simpleCurrency(
      locale: Localizations.localeOf(context).toString());

  return products.map((product) {
    return Card(
      clipBehavior: Clip.antiAlias,
      // TODO: Adjust card heights (103)
      child: Column(
        // TODO: Center items on the card (103)
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          AspectRatio(
            aspectRatio: 18 / 11,
            child: Image.asset(
              product.assetName,
              package: product.assetPackage,
             // TODO: Adjust the box size (102)
            ),
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
              child: Column(
               // TODO: Align labels to the bottom and center (103)
               crossAxisAlignment: CrossAxisAlignment.start,
                // TODO: Change innermost Column (103)
                children: <Widget>[
                 // TODO: Handle overflowing labels (103)
                 Text(
                    product.name,
                    style: theme.textTheme.titleLarge,
                    maxLines: 1,
                  ),
                  const SizedBox(height: 8.0),
                  Text(
                    formatter.format(product.price),
                    style: theme.textTheme.titleSmall,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }).toList();
}

توجه: هنوز کامپایل و اجرا نمی شود. ما یک تغییر دیگر داریم.

همچنین، قبل از اینکه بخواهید کامپایل کنید، تابع build() را تغییر دهید تا BuildContext به _buildGridCards() منتقل شود:

// TODO: Add a grid view (102)
body: GridView.count(
  crossAxisCount: 2,
  padding: const EdgeInsets.all(16.0),
  childAspectRatio: 8.0 / 9.0,
  children: _buildGridCards(context) // Changed code
),

برنامه را دوباره راه اندازی کنید.

اندروید

iOS

شبکه ای از اقلام با تصویر، عنوان محصول و قیمت

شبکه ای از اقلام با تصویر، عنوان محصول و قیمت

ممکن است متوجه شوید که ما هیچ فضای عمودی بین کارت ها اضافه نمی کنیم. به این دلیل که آنها به طور پیش فرض 4 نقطه حاشیه در بالا و پایین خود دارند.

پروژه خود را ذخیره کنید

داده های محصول نشان داده می شود، اما تصاویر فضای اضافی در اطراف خود دارند. تصاویر به طور پیش فرض با یک BoxFit از .scaleDown ترسیم می شوند (در این مورد). بیایید آن را به .fitWidth تغییر دهیم تا آنها کمی بزرگنمایی کنند و فضای خالی اضافی را حذف کنند.

یک فیلد fit: به تصویر با مقدار BoxFit.fitWidth اضافه کنید:

  // TODO: Adjust the box size (102)
  fit: BoxFit.fitWidth,

اندروید

iOS

شبکه ای از اقلام با تصویر برش خورده، عنوان محصول و قیمت

محصولات ما اکنون در برنامه کاملاً نمایش داده می شوند!

7. تبریک می گویم!

برنامه ما یک جریان اساسی دارد که کاربر را از صفحه ورود به صفحه اصلی به صفحه اصلی می برد، جایی که محصولات را می توان مشاهده کرد. فقط در چند خط کد، یک نوار برنامه بالا (با عنوان و سه دکمه) و کارت ها (برای ارائه محتوای برنامه خود) اضافه کردیم. صفحه اصلی ما اکنون ساده و کاربردی است، با ساختار اولیه و محتوای عملی.

مراحل بعدی

با نوار بالای برنامه، کارت، فیلد متن و دکمه، اکنون از چهار جزء اصلی کتابخانه Material Flutter استفاده کرده‌ایم! می‌توانید با مراجعه به کاتالوگ ابزارک‌های مؤلفه‌های مواد، بیشتر کاوش کنید.

در حالی که به طور کامل کار می کند، برنامه ما هنوز مارک یا دیدگاه خاصی را بیان نمی کند. در MDC-103: طرح زمینه طراحی متریال با رنگ، شکل، ارتفاع و نوع ، ما سبک این اجزا را برای بیان یک نام تجاری مدرن و پر جنب و جوش سفارشی می کنیم.

من توانستم با صرف زمان و تلاش معقول این کد لبه را تکمیل کنم

کاملا موافقم موافقم خنثی مخالفت کنید به شدت مخالفم

من می‌خواهم در آینده از Material Component استفاده کنم

کاملا موافقم موافقم خنثی مخالفت کنید به شدت مخالفم