MDC-103 Flutter: עיצוב חומרים עם צבע, צורה, גובה וסוג

1. מבוא

logo_components_color_2x_web_96dp.png

Material Components (MDC) עוזר למפתחים להטמיע Material Design. MDC נוצר על ידי צוות של מהנדסים ומעצבי חוויית המשתמש ב-Google, שכולל עשרות רכיבים יפים ופונקציונליים של ממשק המשתמש. זמין ל-Android, ל-iOS, לאינטרנט ול-Flutter.material.io/develop

עכשיו אפשר להשתמש ב-Material Flutter כדי להתאים אישית את האפליקציות סגנון ייחודי יותר מתמיד. ההתרחבות האחרונה של Material Design מאפשרת למעצבים ולמפתחים יותר גמישות להביע את המותג של המוצר שלהם.

ב-Codelabs MDC-101 ו-MDC-102 השתמשתם ב-Material Flutter כדי ליצור את היסודות של אפליקציה בשם Shrine, אפליקציית מסחר אלקטרוני למכירת בגדים ומוצרים לבית. האפליקציה הזו מכילה תהליך משתמש שמתחיל במסך התחברות, ולאחר מכן מעביר את המשתמשים למסך בית שמוצגים בו מוצרים.

מה תפַתחו

ב-Codelab הזה כדאי להתאים אישית את אפליקציית Shrine באמצעות:

  • צבע
  • טיפוגרפיה
  • גובה
  • צורה
  • פריסה

Android

iOS

דף התחברות למקדש, ורוד וחום מעוצב

דף התחברות למקדש, ורוד וחום מעוצב

דף מוצר בסגנון מקדש, עם סרגל אפליקציה עליון ורשת אסימטרית שאפשר לגלול בה אופקית, מלאה במוצרים, ורוד נושא

רכיבים ומערכות משנה של Material Flutter ב-Codelab הזה

  • עיצובים
  • טיפוגרפיה
  • גובה
  • רשימת תמונות

איזה דירוג מגיע לדעתך לרמת הניסיון שלך בפיתוח Flutter?

מתחילים בינונית בקיאים

2. הגדרת סביבת הפיתוח של Flutter

כדי להשלים את שיעור ה-Lab הזה אתם צריכים שתי תוכנות: Flutter SDK וכלי עריכה.

אפשר להריץ את Codelab באמצעות כל אחד מהמכשירים הבאים:

  • מכשיר פיזי שמשמש ל-Android או ל-iOS שמחובר למחשב ומוגדר ל'מצב פיתוח'.
  • הסימולטור של iOS (צריך להתקין כלים של Xcode).
  • האמולטור של Android (נדרשת הגדרה ב-Android Studio).
  • דפדפן (Chrome נדרש לניפוי באגים).
  • בתור אפליקציית Windows , Linux או macOS למחשב. צריך לפתח בפלטפורמה שבה אתם מתכננים לפרוס. לכן, כדי לפתח אפליקציה למחשב של Windows, צריך לפתח את האפליקציה ב-Windows כדי לגשת לשרשרת ה-build המתאימה. יש דרישות ספציפיות למערכת ההפעלה שמפורטות בהרחבה בכתובת docs.flutter.dev/desktop.

3. הורדת האפליקציה לתחילת העבודה של Codelab

ממשיכים לעבור מ-MDC-102?

אם השלמתם את MDC-102, הקוד אמור להיות מוכן לשימוש ב-Codelab הזה. דלגו לשלב שינוי הצבעים.

מתחילים מאפס?

להורדת האפליקציה לתחילת פעולה של Codelab

האפליקציה לתחילת הפעולה נמצאת בספרייה material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series.

...או לשכפל אותו מ-GitHub

כדי לשכפל את ה-Codelab הזה מ-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

פותחים את הפרויקט ומפעילים את האפליקציה

  1. פותחים את הפרויקט בכלי עריכה לבחירתכם.
  2. פועלים לפי ההוראות ל'הפעלת האפליקציה'. בקטע תחילת העבודה: נסיעת מבחן עבור העורך שנבחר.

הצלחת! אתם אמורים לראות במכשיר את דף ההתחברות ל-Shhine מ-Codelabs הקודמים.

Android

iOS

דף התחברות למקדש לא מעוצב

דף התחברות למקדש לא מעוצב

לוחצים על 'הבא'. כדי לראות את דף המוצר.

Android

iOS

דף רשת מוצרים במקדש לא מעוצב

דף רשת מוצרים במקדש לא קשור

4. שינוי הצבעים

נוצרה ערכת צבעים שמייצגת את המותג Shrine, והמעצב מעוניין להטמיע את ערכת הצבעים הזו באפליקציית Shrine

כדי להתחיל, נייבא את הצבעים האלה לפרויקט שלנו.

יצירה colors.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 2014).

הכלי Material Theme Editor ארגן אותם בגוונים לפי מספר, כולל תוויות 50, 100, 200, .... עד 900 מכל צבע. הגוון 50, 100 ו-300 מהדוגמית הוורודה ו-900 מהדוגמית החום משתמשים בגוונים בלבד.

d0362cb45c565a8e.jpeg 470b0e1c2669ae2.png

כל פרמטר צבעוני של ווידג'ט ממופה לצבע מהערכות האלה. לדוגמה, הצבע של קישוטים לשדה טקסט בזמן שהוא מקבל קלט באופן פעיל צריך להיות הצבע הראשי של העיצוב. אם הצבע הזה לא נגיש (קל לראות אותו על הרקע שלו), השתמשו בצבע אחר במקום זאת.

עכשיו, אחרי ששמענו את הצבעים שאנחנו רוצים להשתמש בהם, אנחנו יכולים להחיל אותם על ממשק המשתמש. לשם כך נקבע את הערכים של ווידג'ט ThemeData שאנחנו מחילים על מופע ה-MaterialApp שנמצא בחלק העליון של היררכיית הווידג'טים שלנו.

התאמה אישית של ThemeData.light()

Flutter כוללת כמה עיצובים מובנים. העיצוב הבהיר הוא אחד מהם. במקום ליצור ווידג'ט של ThemeData מאפס, נעתיק את העיצוב הבהיר ונשנה את הערכים כדי להתאים אותם אישית לאפליקציה שלנו.

עכשיו נייבא את colors.dart ב-app.dart.

import 'colors.dart';

לאחר מכן מוסיפים את הפקודה הבאה אל app.dart מחוץ להיקף המחלקה ShrineApp:

// 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

דף התחברות למקדש בעיצוב ורוד וחום

דף התחברות למקדש בעיצוב ורוד וחום

5. שינוי הסגנונות של הטיפוגרפיה והתוויות

מלבד השינויים בצבעים, המעצב נתן לנו גם טיפוגרפיה ספציפית לשימוש. ה-ThemeData של Flutter כולל 3 עיצובי טקסט. כל עיצוב של טקסט הוא אוסף של סגנונות טקסט, כמו "כותרת" ו-'title'. אנחנו נשתמש בכמה סגנונות לאפליקציה שלנו ונשנה חלק מהערכים.

התאמה אישית של עיצוב הטקסט

כדי לייבא גופנים לפרויקט, צריך להוסיף אותם לקובץ 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. אם מופיעות שגיאות, קודם כול מסירים את הרווח הלבן המוביל ומחליפים אותו ברווחים באמצעות כניסת פסקה עם 2 רווחים. (שני רווחים לפני

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() (כותרת, כותרת, כיתוב).

עבור גופנים מסוימים, אנחנו מגדירים גופן מותאם אישית במרווחים של 100: w500 (המשקל 500) תואם לבינוני ו-w400 תואם לערך רגיל.

השתמשו בטקסט החדשבנושאים

מוסיפים את העיצובים הבאים אל _buildShrineTheme אחרי השגיאה:

// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
  selectionColor: kShrinePink100,
),

שומרים את הפרויקט. הפעם צריך גם להפעיל מחדש את האפליקציה (שנקראת הפעלה מחדש חמה), כי שינינו גופנים.

Android

iOS

דף רשת מוצרים של משבצות עם עיצובי טקסט

הטקסט במסכי ההתחברות ובמסכי הבית נראים אחרת. טקסט מסוים מופיע בגופן רוביק, וטקסטים אחרים מוצגים בצבע חום במקום בשחור או לבן. סמלים מופיעים גם בצבע חום.

כיווץ הטקסט

התוויות גדולות מדי.

בקובץ 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

דף התחברות למקדש עם התמקדות בשדה שם המשתמש

דף התחברות למקדש עם התמקדות בשדה שם המשתמש

מקלידים בשדה טקסט – הגבולות והתוויות הצפות מוצגים בצבע הראשי. אבל קשה לנו לראות אותה. המצב הזה לא נגיש לאנשים שמתקשים להבדיל בין פיקסלים שאין בהם ניגודיות צבעים גבוהה מספיק. (למידע נוסף, עיינו במאמר על צבע ונגישות.)

ב-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

דף התחברות למקדש עם לחצן &#39;ביטול&#39; נגיש

דף התחברות למקדש עם לחצן &#39;ביטול&#39; נגיש

6. התאמת הגובה

עכשיו, לאחר שעיצבתם את הדף לצבע ולטיפוגרפיה ספציפיים שתואמים ל'מקדש', נתאים את הגובה.

שינוי הגובה של הלחצן 'הבא'

גובה ברירת המחדל של ElevatedButton הוא 2. כדאי להעלות אותה למעלה.

ב-login.dart, צריך להוסיף ערך של style: ללחצן הגבוה הבא:

ElevatedButton(
  child: const Text('NEXT'),
  onPressed: () {
    Navigator.pop(context);
  },
  style: ElevatedButton.styleFrom(
    foregroundColor: kShrineBrown900,
    backgroundColor: kShrinePink100,
    elevation: 8.0,
  ),
),

שומרים את הפרויקט.

Android

iOS

דף התחברות למקדש עם לחצן NEXT מוגבה

דף התחברות למקדש עם לחצן NEXT מוגבה

שינוי הגובה של הכרטיס

בשלב זה הכרטיסים מוצבים על משטח לבן לצד הניווט באתר.

ב-home.dart, מוסיפים ערך של elevation: לכרטיסים:

// TODO: Adjust card heights (103)
elevation: 0.0,

שומרים את הפרויקט.

Android

iOS

דף רשת מוצרים של מקדש ללא גובה לכל כרטיס

דף רשת מוצרים של מקדש ללא גובה עבור כל כרטיס

הסרת את הצללית שמתחת לכרטיסים.

7. הוספת צורה

למקדש יש סגנון גיאומטרי מגניב שמגדיר אלמנטים עם צורה מתומן או מלבנית. עכשיו נטמיע את עיצוב הצורה הזה בכרטיסים במסך הבית ובשדות הטקסט ובלחצנים במסך ההתחברות.

שינוי הצורות של שדות הטקסט במסך ההתחברות

ב-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)),
    ),
  ),
),

ל'לחצן הטקסט' אין צורה נראית לעין, אז למה להוסיף צורה של גבול? כך, אנימציית הגלים מקושרת לאותה צורה כשנוגעים בה.

עכשיו מוסיפים את אותה הצורה ללחצן 'הבא':

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

דף התחברות למקדש עם עיצוב עיצובים

דף התחברות למקדש עם עיצוב עיצובים

8. שינוי הפריסה

בשלב הבא נשנה את הפריסה כדי להציג כרטיסים ביחסי גובה-רוחב ובגדלים שונים, כך שכל כרטיס ייראה ייחודי מהאחרים.

החלפת GridView ב-AsymmetricView

כבר כתבנו את הקבצים לפריסה אסימטרית.

ב-home.dart, מוסיפים את הייבוא הבא:

import 'supplemental/asymmetric_view.dart';

מוחקים את _buildGridCards ומחליפים את השדה body:

body: AsymmetricView(
  products: ProductsRepository.loadProducts(Category.all),
),

שומרים את הפרויקט.

Android

iOS

דף מוצר בצורת שוליים עם פריסה אסימטרית שניתנת לגלילה אופקית

דף מוצר בצורת שוליים עם פריסה אסימטרית שניתנת לגלילה אופקית

עכשיו המוצרים נגללים לרוחב בסגנון ארוג.

9. כדאי לנסות עיצוב אחר (אופציונלי)

צבע הוא דרך יעילה לבטא את המותג שלך, ושינוי קטן בצבע יכול להשפיע באופן משמעותי על חוויית המשתמש. כדי לבדוק את זה, בואו נראה איך 'מקדש' נראה אם העיצוב של המותג שונה מעט.

שינוי הצבעים

ב-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

דף מוצר בסגנון מקדש ורוד עם עיצוב ורוד

דף מוצר בסגנון מקדש ורוד עם עיצוב ורוד

התוצאה שונה מאוד! נחזיר את _buildShrineTheme של app.dart's למה שהיה לפני השלב הזה. לחלופין, אפשר להוריד את קוד ההתחלה של קוד 104.

10. מעולה!

עד עכשיו יצרתם אפליקציה שדומה למפרטי העיצוב של המעצב שלכם.

השלבים הבאים

השתמשת עכשיו ב-Material Flutter: עיצוב, טיפוגרפיה, גובה וצורה. אפשר לחקור עוד רכיבים ומערכות משנה בספרייה Material Flutter.

אפשר לעיין בקבצים בספרייה supplemental כדי לראות איך יצרנו את רשת הפריסה האסימטרית של הגלילה האופקית.

מה קורה אם עיצוב האפליקציה המתוכנן מכיל אלמנטים שאין להם רכיבים בספרייה? בקורס MDC-104: Material Advanced Components נסביר איך ליצור רכיבים מותאמים אישית באמצעות ספריית Material Flutter כדי להשיג מראה רצוי.

הצלחתי להשלים את ה-Codelab הזה תוך השקעה של זמן ומאמץ סבירים

נכון מאוד נכון נייטרלי לא נכון לא נכון בכלל

ארצה להמשיך להשתמש ברכיבי Material Materials בעתיד

נכון מאוד נכון נייטרלי לא נכון לא נכון בכלל