۱. مقدمه
| «عناصر Material» (MDC) به توسعهدهندگان کمک میکند «طراحی مواد» را پیادهسازی کنند. MDC که توسط تیمی از مهندسان و طراحان تجربه کاربری در Google ایجاد شده است، دهها مؤلفه واسط کاربر زیبا و کاربردی دارد و برای Android، iOS، وب، و Flutter دردسترس است.material.io/develop |
اکنون میتوانید از Material Flutter برای سفارشیسازی سبک متمایز برنامههایتان بیشاز همیشه استفاده کنید. گسترش اخیر «طراحی مواد» به طراحان و توسعهدهندگان انعطافپذیری بیشتری برای بیان نمانام محصولشان میدهد.
در codelabs MDC-101 و MDC-102، از Material Flutter برای ساختن اصول اولیه برنامهای بهنام Shrine، یک برنامه تجارت الکترونیک که لباس و لوازم منزل میفروشد، استفاده کردید. این برنامه حاوی جریان کاربری است که با صفحه ورود به سیستم شروع میشود، سپس کاربر را به صفحه اصلی میبرد که محصولات را نمایش میدهد.
آنچه خواهید ساخت
در این codelab، برنامه Shrine را بااستفاده از موارد زیر سفارشیسازی خواهید کرد:
- رنگ
- تایپوگرافی
- ارتفاع
- شکلها
- چیدمان
Android | iOS |
|
|
|
|
زیرسیستمها و عناصر Material Flutter در این codelab
- زمینه
- تایپوگرافی
- ارتفاع
- فهرست تصویر
سطح تجربه خود را در توسعه Flutter چگونه ارزیابی میکنید؟
۲. راهاندازی محیط توسعه Flutter
برای تکمیل این آزمایشگاه به دو نرمافزار نیاز دارید: کیت توسعه نرمافزار Flutter و ویرایشگر.
میتوانید بااستفاده از هریک از این دستگاهها، دستورات تمرینی را اجرا کنید:
- دستگاه فیزیکی Android یا iOS که به رایانه شما متصل شده و روی حالت «توسعهدهنده» تنظیم شده باشد.
- شبیهساز iOS (نیاز به نصب ابزارهای Xcode دارد).
- شبیهساز Android (نیاز به راهاندازی در «استودیو Android» دارد).
- مرورگر (برای اشکالزدایی، Chrome الزامی است).
- بهعنوان برنامه رایانهای Windows، Linux، یا macOS. باید در پلاتفرمی که قصد دارید در آن مستقر کنید توسعه دهید. بنابراین، اگر میخواهید برنامه رایانهای Windows توسعه دهید، باید در Windows توسعه دهید تا به زنجیره ساخت مناسب دسترسی داشته باشید. الزامات خاص سیستمعامل وجود دارد که بهطور مفصل در docs.flutter.dev/desktop پوشش داده شده است.
۳. بارگیری برنامه آغازگر codelab
از MDC-102 ادامه میدهید؟
اگر MDC-102 را تکمیل کردهاید، کد شما باید برای این codelab آماده باشد. به این مرحله بروید: تغییر رنگها.
از اول شروع میکنید؟
بارگیری برنامه codelab آغازگر
برنامه آغازگر در فهرست راهنمای material-components-flutter-codelabs-103-starter_and_102-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 103-starter_and_102-complete
پروژه را باز کنید و برنامه را اجرا کنید
- پروژه را در ویرایشگر دلخواهتان باز کنید.
- دستورالعملهای «اجرای برنامه» را در شروع به کار: تست درایو برای ویرایشگر انتخابیتان دنبال کنید.
موفقیتآمیز بود. باید صفحه ورود به سیستم Shrine را از کدآزمای قبلی در دستگاهتان ببینید.
Android | iOS |
|
|
برای دیدن صفحه محصول، روی «بعدی» کلیک کنید.
Android | iOS |
|
|
۴. تغییر رنگها
آرایش رنگیای ایجاد شده است که نشاندهنده نمانام Shrine است و طراح میخواهد آن آرایش رنگی را در سراسر برنامه Shrine پیادهسازی کنید
برای شروع، بیایید این رنگها را به پروژهمان وارد کنیم.
ایجاد colors.dart
فایل dart جدیدی در lib بهنام colors.dart ایجاد کنید. وارد کردن material.dart و افزودن const Color مقدار:
import 'package:flutter/material.dart';
const kShrinePink50 = Color(0xFFFEEAE6);
const kShrinePink100 = Color(0xFFFEDBD0);
const kShrinePink300 = Color(0xFFFBB8AC);
const kShrinePink400 = Color(0xFFEAA4A4);
const kShrineBrown900 = Color(0xFF442B2D);
const kShrineErrorRed = Color(0xFFC5032B);
const kShrineSurfaceWhite = Color(0xFFFFFBFA);
const kShrineBackgroundWhite = Colors.white;
پالت رنگ سفارشی
این زمینه رنگی توسط طراح با رنگهای سفارشی (در تصویر زیر نشان داده شده است) ایجاد شده است. این پالت حاوی رنگهایی است که از نمانام Shrine انتخاب شده و در Material Theme Editor اعمال شده است، که آنها را گسترش داده تا پالت کاملتری ایجاد کند. (این رنگها از پالتهای رنگ Material ۲۰۱۴ نیستند.)
«ویرایشگر زمینه Material» آنها را در سایههایی که بهصورت عددی برچسبگذاری شدهاند، ازجمله برچسبهای ۵۰، ۱۰۰، ۲۰۰، تا ۹۰۰ برای هر رنگ، سازماندهی کرده است. Shrine فقط از رنگهای ۵۰، ۱۰۰، و ۳۰۰ از نمونه رنگ صورتی و ۹۰۰ از نمونه رنگ قهوهای استفاده میکند.

هر پارامتر رنگی ابزاره به رنگی از این طرحها نگاشت میشود. برای مثال، رنگ تزئینات فیلد نوشتاری وقتی بهطور فعال ورودی دریافت میکند باید «رنگ اصلی» زمینه باشد. اگر آن رنگ دسترسپذیر نیست (دیدن آن در پسزمینهاش آسان نیست)، بهجای آن از رنگ دیگری استفاده کنید.
اکنون که رنگهای موردنظرمان را داریم، میتوانیم آنها را روی رابط کاربری اعمال کنیم. این کار را با تنظیم مقادیر ابزاره ThemeData انجام میدهیم که آن را در بالای سلسلهمراتب ابزارهمان بر نمونه MaterialApp اعمال میکنیم.
سفارشیسازی ThemeData.light()
Flutter شامل چند موضوع داخلی است. زمینه روشن یکی از آنها است. بهجای ساختن ابزاره ThemeData از ابتدا، زمینه روشن را کپی میکنیم و مقادیر را تغییر میدهیم تا آنها را برای برنامهمان سفارشیسازی کنیم.
بیایید colors.dart را در app.dart. وارد کنیم
import 'colors.dart';
سپس موارد زیر را خارج از محدوده کلاس ShrineApp به app.dart اضافه کنید:
// TODO: Build a Shrine Theme (103)
final ThemeData _kShrineTheme = _buildShrineTheme();
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light(useMaterial3: true);
return base.copyWith(
colorScheme: base.colorScheme.copyWith(
primary: kShrinePink100,
onPrimary: kShrineBrown900,
secondary: kShrineBrown900,
error: kShrineErrorRed,
),
// TODO: Add the text themes (103)
// TODO: Decorate the inputs (103)
);
}
اکنون، theme: را در انتهای تابع build() در ShrineApp (در ابزاره MaterialApp) تنظیم کنید تا زمینه جدید ما باشد:
// TODO: Customize the theme (103)
theme: _kShrineTheme, // New code
پروژهتان را ذخیره کنید. صفحه ورود به سیستم شما اکنون باید به این شکل باشد:
Android | iOS |
|
|
۵. اصلاح سبکهای برچسب و حروفچینی
علاوهبر تغییرات رنگ، طراح همچنین طرح حروف خاصی را برای استفاده به ما داده است. ThemeData در Flutter شامل ۳ زمینه نوشتار است. هر زمینه نوشتاری مجموعهای از سبکهای نوشتار است، مثل «عنوان اصلی» و «عنوان». از چند سبک برای برنامهمان استفاده میکنیم و برخیاز مقادیر را تغییر میدهیم.
سفارشیسازی کردن زمینه نوشتار
برای وارد کردن قلمها به پروژه، باید آنها را به فایل pubspec.yaml اضافه کنید.
در pubspec.yaml، موارد زیر را بلافاصله پساز برچسب flutter: اضافه کنید:
# TODO: Insert Fonts (103)
fonts:
- family: Rubik
fonts:
- asset: fonts/Rubik-Regular.ttf
- asset: fonts/Rubik-Medium.ttf
weight: 500
اکنون میتوانید به قلم Rubik دسترسی داشته باشید و از آن استفاده کنید.
عیبیابی فایل pubspec
اگر بیانیه بالا را برش دهید و جایگذاری کنید، ممکن است در اجرای pub get با خطا مواجه شوید. اگر با خطا مواجه شدید، ابتدا فاصله سفید ابتدایی را بردارید و آن را با فاصلههایی با تورفتگی ۲ فاصلهای جایگزین کنید. (دو فاصله قبلاز
fonts:
، چهار فاصله قبلاز
family: Rubik
، و غیره.)
اگر مقادیر نگاشت در اینجا مجاز نیست را دیدید، تورفتگی خطی که مشکل دارد و تورفتگی خطوط بالای آن را بررسی کنید.
در login.dart، موارد زیر را در Column() تغییر دهید:
Column(
children: <Widget>[
Image.asset('assets/diamond.png'),
const SizedBox(height: 16.0),
Text(
'SHRINE',
style: Theme.of(context).textTheme.headlineSmall,
),
],
)
در app.dart، موارد زیر را پساز _buildShrineTheme() اضافه کنید:
// TODO: Build a Shrine Text Theme (103)
TextTheme _buildShrineTextTheme(TextTheme base) {
return base
.copyWith(
headlineSmall: base.headlineSmall!.copyWith(
fontWeight: FontWeight.w500,
),
titleLarge: base.titleLarge!.copyWith(
fontSize: 18.0,
),
bodySmall: base.bodySmall!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14.0,
),
bodyLarge: base.bodyLarge!.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16.0,
),
)
.apply(
fontFamily: 'Rubik',
displayColor: kShrineBrown900,
bodyColor: kShrineBrown900,
);
}
این کار یک TextTheme را میگیرد و ظاهر عنوانها، عنوانها، و زیرنویسهای ناشنوایان را تغییر میدهد.
اعمال کردن fontFamily به این روش، تغییرات را فقط روی مقادیر مقیاس تایپوگرافی مشخصشده در copyWith() (عنوان، عنوان، زیرنویس) اعمال میکند.
برای برخیاز قلمها، وزن قلم سفارشی را با افزایش ۱۰۰ واحدی تنظیم میکنیم: w500 (وزن ۵۰۰) معادل متوسط و w400 معادل معمولی است.
استفاده از نوشتار جدیدقالب
موضوعهای زیر پساز خطا به _buildShrineTheme اضافه شود:
// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
selectionColor: kShrinePink100,
),
پروژهتان را ذخیره کنید. این بار، برنامه را نیز بازراهاندازی کنید (که بهعنوان بازراهاندازی داغ شناخته میشود)، زیرا قلمها را تغییر دادهایم.
Android | iOS |
|
|
نوشتار در صفحه ورود به سیستم و صفحه اصلی متفاوت بهنظر میرسد—برخیاز نوشتارها از قلم Rubik استفاده میکنند و برخی دیگر بهجای سیاه یا سفید، به رنگ قهوهای ارائه میشوند. نمادها نیز به رنگ قهوهای ارائه میشوند.
کوچک کردن نوشتار
برچسبها خیلی بزرگ هستند.
در home.dart، children: داخلیترین «ستون» را تغییر دهید:
// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
Text(
product.name,
style: theme.textTheme.button,
softWrap: false,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
const SizedBox(height: 4.0),
Text(
formatter.format(product.price),
style: theme.textTheme.bodySmall,
),
// End new code
],
نوشتار را در مرکز قرار دهید و رها کنید
میخواهیم برچسبها را در مرکز قرار دهیم و نوشتار را بهجای پایین هر تصویر، در پایین هر کارت تراز کنیم.
برچسبها را به انتهای (پایین) محور اصلی منتقل کنید و آنها را به مرکز تغییر دهید::
// TODO: Align labels to the bottom and center (103)
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
پروژهتان را ذخیره کنید.
Android | iOS |
|
|
این خیلی بهتر است.
زمینه فیلدهای نوشتاری
همچنین میتوانید تزئینات فیلدهای نوشتاری را با InputDecorationTheme زمینهبندی کنید.
در app.dart، در روش _buildShrineTheme()، مقدار inputDecorationTheme: را مشخص کنید:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
),
درحالحاضر، فیلدهای نوشتاری تزئین filled دارند. بیایید آن را برداریم. برداشتن filled و مشخص کردن inputDecorationTheme به فیلدهای نوشتار سبک رئوس مطالب میدهد.
در login.dart، مقادیر filled: true را بردارید:
// Remove filled: true values (103)
TextField(
controller: _usernameController,
decoration: const InputDecoration(
// Removed filled: true
labelText: 'Username',
),
),
const SizedBox(height: 12.0),
TextField(
controller: _passwordController,
decoration: const InputDecoration(
// Removed filled: true
labelText: 'Password',
),
obscureText: true,
),
بازراهاندازی داغ. وقتی فیلد «نام کاربری» فعال است (وقتی در آن تایپ میکنید)، صفحه ورود به سیستم باید به این شکل باشد:
Android | iOS |
|
|
در فیلد نوشتاری تایپ کنید—حاشیهها و برچسبهای شناور با رنگ اصلی ارائه میشوند. اما نمیتوانیم آن را بهراحتی ببینیم. برای افرادی که در تشخیص پیکسلهایی که کنتراست رنگ کافی ندارند مشکل دارند، قابلدسترس نیست. (برای اطلاعات بیشتر، به مقاله رنگ و دسترسپذیری در «رهنمودهای Material» مراجعه کنید.)
در app.dart، focusedBorder: را در inputDecorationTheme: مشخص کنید :
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
),
سپس، floatingLabelStyle: را در inputDecorationTheme: مشخص کنید :
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
در آخر، بیایید دکمه «لغو» را بهجای رنگ اصلی از رنگ فرعی استفاده کنیم تا کنتراست افزایش یابد.
TextButton(
child: const Text('CANCEL'),
onPressed: () {
_usernameController.clear();
_passwordController.clear();
},
style: TextButton.styleFrom(
primary: Theme.of(context).colorScheme.secondary,
),
),
پروژهتان را ذخیره کنید.
Android | iOS |
|
|
۶. تنظیم ارتفاع
اکنون که صفحه را با رنگ و حروفچینی خاصی که با Shrine مطابقت دارد سبکبندی کردهاید، بیایید ارتفاع را تنظیم کنیم.
تغییر ارتفاع دکمه «بعدی»
ارتفاع پیشفرض برای ElevatedButton، ۲ است. بیایید آن را بالاتر ببریم.
در login.dart، مقدار style: را به NEXT «دکمه برجسته» اضافه کنید:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
foregroundColor: kShrineBrown900,
backgroundColor: kShrinePink100,
elevation: 8.0,
),
),
پروژهتان را ذخیره کنید.
Android | iOS |
|
|
تنظیم ارتفاع کارت
درحالحاضر، کارتها روی سطحی سفید در کنار پیمایش سایت قرار دارند.
در home.dart، مقدار elevation: را به «کارتها» اضافه کنید:
// TODO: Adjust card heights (103)
elevation: 0.0,
پروژه را ذخیره کنید.
Android | iOS |
|
|
سایه زیر کارتها را برداشتهاید.
۷. افزودن شکل
Shrine سبک هندسی جالبی دارد و عناصر را با شکل هشتضلعی یا مستطیلی تعریف میکند. بیایید آن سبکدهی شکل را در کارتهای صفحه اصلی و فیلدهای نوشتاری و دکمههای صفحه ورود به سیستم پیادهسازی کنیم.
تغییر شکلهای فیلد نوشتاری در صفحه ورود به سیستم
در app.dart، فایل زیر را وارد کنید:
import 'supplemental/cut_corners_border.dart';
همچنان در app.dart، زمینه تزئین فیلد نوشتاری را تغییر دهید تا از حاشیه گوشههای بریده استفاده کنید:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: CutCornersBorder(),
focusedBorder: CutCornersBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
تغییر شکل دکمهها در صفحه ورود به سیستم
در login.dart، به دکمه لغو حاشیه مستطیلی پخ اضافه کنید:
TextButton(
child: const Text('CANCEL'),
onPressed: () {
_usernameController.clear();
_passwordController.clear();
},
style: TextButton.styleFrom(
foregroundColor: kShrineBrown900,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
),
),
TextButton شکل نمایانی ندارد، پس چرا باید شکل حاشیهای اضافه کنیم؟ بنابراین پویانمایی موجی هنگام لمس به همان شکل محدود میشود.
اکنون همان شکل را به دکمه «بعدی» اضافه کنید:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
foregroundColor: kShrineBrown900,
backgroundColor: kShrinePink100,
elevation: 8.0,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
),
),
برای تغییر شکل همه دکمهها، میتوانیم از elevatedButtonTheme یا textButtonTheme در app.dart نیز استفاده کنیم. این بهعنوان چالشی برای یادگیرنده باقی میماند!
بازراهاندازی داغ.
Android | iOS |
|
|
۸. تغییر دادن چیدمان
سپس، بیایید چیدمان را تغییر دهیم تا کارتها با نسبتهای ابعادی و اندازههای مختلف نمایش داده شوند، بهطوری که هر کارت نسبتبه کارتهای دیگر منحصربهفرد بهنظر برسد.
جایگزین کردن GridView با AsymmetricView
ما قبلاً فایلهای چیدمان نامتقارن را نوشتهایم.
در home.dart، وارد کردن زیر را اضافه کنید:
import 'supplemental/asymmetric_view.dart';
حذف _buildGridCards و جایگزین کردن body:
body: AsymmetricView(
products: ProductsRepository.loadProducts(Category.all),
),
پروژه را ذخیره کنید.
Android | iOS |
|
|
اکنون محصولات بهصورت افقی در الگویی الهامگرفته از بافت حرکت میکنند.
۹. امتحان کردن زمینهای دیگر (اختیاری)
رنگ روشی قدرتمند برای بیان کردن نمانام شما است و تغییر کوچکی در رنگ میتواند تأثیر بزرگی بر تجربه کاربری شما داشته باشد. برای آزمایش این موضوع، بیایید ببینیم اگر طرح رنگ نمانام کمی متفاوت بود، Shrine چه شکلی میشد.
اصلاح رنگها
در colors.dart، رنگ زیر را اضافه کنید:
const kShrinePurple = Color(0xFF5D1049);
در app.dart، تابع _buildShrineTheme() را به موارد زیر تغییر دهید:
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light();
return base.copyWith(
colorScheme: base.colorScheme.copyWith(
primary: kShrinePurple,
secondary: kShrinePurple,
error: kShrineErrorRed,
),
scaffoldBackgroundColor: kShrineSurfaceWhite,
textSelectionTheme: const TextSelectionThemeData(
selectionColor: kShrinePurple,
),
appBarTheme: const AppBarTheme(
foregroundColor: kShrineBrown900,
backgroundColor: kShrinePink100,
),
inputDecorationTheme: const InputDecorationTheme(
border: CutCornersBorder(),
focusedBorder: CutCornersBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrinePurple,
),
),
floatingLabelStyle: TextStyle(
color: kShrinePurple,
),
),
);
}
بازراهاندازی داغ. اکنون باید زمینه جدید نمایش داده شود.
Android | iOS |
|
|
Android | iOS |
|
|
نتیجه بسیار متفاوت است! بیایید app.dart's _buildShrineTheme را به آنچه قبلاز این مرحله بود برگردانیم. یا کد آغازگر 104 را بارگیری کنید.
۱۰. تبریک!
تاکنون برنامهای ساختهاید که شبیه مشخصات طراحی طراح شما است.
مراحل بعدی
اکنون از موارد زیر در Material Flutter استفاده کردهاید: زمینه، حروفچینی، ارتفاع، و شکل. میتوانید اجزا و زیرسیستمهای بیشتری را در کتابخانه Material Flutter کاوش کنید.
برای آشنایی با نحوه ساختن شبکه چیدمان نامتقارن با پیمایش افقی، فایلهای فهرست راهنمای supplemental را بررسی کنید.
اگر طراحی برنامهریزیشده برنامهتان حاوی عناصری باشد که مؤلفهای در کتابخانه ندارند، چه اتفاقی میافتد؟ در MDC-104: عناصر پیشرفته Material نشان میدهیم که چگونه بااستفاده از کتابخانه Material Flutter عناصر سفارشی ایجاد کنید تا به ظاهر دلخواه برسید.


























