חפש מדריכים

מדריך Flutter מלא בעברית

מדריך זה מציע מסלול מלא למתחילים ולמתקדמים: מהתקנה, דרך בניית ממשק, ועד חיבור ל-API, ניהול state ו-Flutter Web עם JS.

מדריך זה מציע מסלול מלא למתחילים ולמתקדמים: מהתקנה, דרך בניית ממשק, ועד חיבור ל-API, ניהול state ו-Flutter Web עם JS.

מה זה Flutter?

Flutter היא מסגרת עבודה של Google לבניית ממשקי משתמש לכל המכשירים: אנדרואיד, iOS, Web ושולחן עבודה. היא משתמשת בשפת Dart ומייצרת ממשק מהיר, מודרני ותגובה גבוהה.

כשהאפליקציה רצה בפלוטר, כל המסך נבנה מרכיבים שנקראים Widgets. כל דבר שנראה על המסך הוא Widget בסופו של דבר.

התקנה ויצירת פרויקט

  1. הורד והתקן את Flutter SDK מהאתר הרשמי: flutter.dev.
  2. ודא שיש לך גם Dart ו-Android Studio / Visual Studio Code.
  3. בחיבור למסוף, הרץ:
flutter doctor

אם הכל בסדר, תראה מסך שמראה את המצב של Flutter, Dart, Android, iOS ו-Web.

יצירת פרויקט חדש

flutter create my_app
cd my_app

לאחר מכן תוכל להריץ:

flutter run

זה יריץ את האפליקציה על אמולטור או מכשיר מחובר.

פקודות שימושיות נוספות ב-Flutter

אלו הפקודות החשובות ביותר שכדאי לדעת כדי לעבוד עם פרויקט Flutter בסיסי.

עדכון תלותות והרצת בדיקות מהירות

flutter pub get
flutter pub upgrade
flutter analyze

flutter pub get מוריד את התלויות שהוגדרו ב-pubspec.yaml.

flutter pub upgrade מעדכן לגרסאות האחרונות שניתן להשתמש בהן.

flutter analyze בודק בעיות סינטקס וקוד בפרויקט.

בניה על פלטפורמות שונות

flutter build apk
flutter build appbundle
flutter build web
flutter build ipa

המחרוזות האלה בונות את האפליקציה ל-Android (APK או App Bundle), ל-Web או ל-iOS.

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

flutter devices
flutter emulators
flutter emulators --launch 

flutter devices מראה לך על אילו מכשירים אפשר להריץ.

flutter emulators מנהל את מכשירי האמולציה הזמינים.

לאחר שהמכשיר או האמולטור מחובר, שוב הרץ flutter run.

מבנה פרויקט Flutter

הפרויקט הנוצר כולל את התיקיות והשדות הראשיים:

  • lib/main.dart - קובץ הכניסה לאפליקציה.
  • pubspec.yaml - הגדרות תלותיות, assets, שם האפליקציה ועוד.
  • android/, ios/, web/ - חלקים ספציפיים לכל פלטפורמה.

הקובץ החשוב ביותר בעת לימוד הוא lib/main.dart, שם נגדיר את המבנה הבסיסי של האפליקציה.

דוגמה פשוטה ל-main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'שלום Flutter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('דף הבית'),
      ),
      body: const Center(
        child: Text('שלום עולם בפלוטר!'),
      ),
    );
  }
}

Dart - העקרונות הבסיסיים

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

משתנים וטיפוסים

void main() {
  String name = 'Dart';
  int age = 10;
  double price = 19.99;
  bool isReady = true;

  print('השם שלי הוא $name');
  print('גיל: $age');
  print('מחיר: $price');
  print('מוכן? $isReady');
}

רשימות ומפות

void main() {
  List names = ['אורי', 'נועה', 'תמר'];
  Map scores = {
    'אורי': 90,
    'נועה': 85,
  };

  print(names[0]);
  print(scores['אורי']);
}

לולאות ותנאים

void main() {
  for (var i = 1; i <= 5; i++) {
    print('מספר $i');
  }

  int value = 7;
  if (value > 5) {
    print('גדול מ-5');
  } else {
    print('לא גדול מ-5');
  }
}

פונקציות

String greet(String name) {
  return 'שלום $name';
}

void main() {
  print(greet('דנה'));
}

מחלקות ו-constructors

class User {
  final String name;
  final int age;

  User({required this.name, required this.age});
}

void main() {
  final user = User(name: 'יונתן', age: 25);
  print('השם: ${user.name}, גיל: ${user.age}');
}

Widgets בפלוטר

Widgets הם אבן הבניין של כל ממשק Flutter. יש שני סוגים חשובים:

  • StatelessWidget - Widget סטטי שאינו משנה את עצמו.
  • StatefulWidget - Widget עם מצב פנימי שניתן לעדכן.

StatelessWidget

class HelloWidget extends StatelessWidget {
  const HelloWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Text('שלום!');
  }
}

StatefulWidget

class CounterPage extends StatefulWidget {
  const CounterPage({Key? key}) : super(key: key);

  @override
  State createState() => _CounterPageState();
}

class _CounterPageState extends State {
  int counter = 0;

  void increase() {
    setState(() {
      counter += 1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('לחיצות: $counter'),
        ElevatedButton(
          onPressed: increase,
          child: const Text('הגדל'),
        ),
      ],
    );
  }
}

השורה החשובה היא setState(). היא גורמת לפלוטר להריץ את build שוב ולהציג את העדכון.

עיצוב ומבנה מסכים

Flutter מאפשר לבנות פריסות דרך Widgets ייעודיים כמו Row, Column, Container ו-Expanded.

מבנה מסך פשוט

class LayoutExample extends StatelessWidget {
  const LayoutExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Layout Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              padding: const EdgeInsets.all(16),
              color: Colors.blue.shade100,
              child: const Text('קופסה עם רווחים'),
            ),
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                Icon(Icons.star, color: Colors.amber),
                SizedBox(width: 10),
                Text('שורה עם אייקון וטקסט'),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

רשימה גלילה

class ListExample extends StatelessWidget {
  const ListExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ListView Example')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: List.generate(
          10,
          (index) => Card(
            margin: const EdgeInsets.symmetric(vertical: 8),
            child: ListTile(
              title: Text('פריט ${index + 1}'),
              subtitle: const Text('כותרת משנה'),
            ),
          ),
        ),
      ),
    );
  }
}

ניהול State והפעלת קוד

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

דוגמה לטופס פשוט

class FormPage extends StatefulWidget {
  const FormPage({Key? key}) : super(key: key);

  @override
  State createState() => _FormPageState();
}

class _FormPageState extends State {
  final _controller = TextEditingController();
  String message = '';

  void submit() {
    setState(() {
      message = 'המשתמש כתב: ${_controller.text}';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Form Example')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            TextField(
              controller: _controller,
              decoration: const InputDecoration(labelText: 'כתבו משהו'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: submit,
              child: const Text('שלח'),
            ),
            const SizedBox(height: 20),
            Text(message),
          ],
        ),
      ),
    );
  }
}

הטיפול בקלט מתבצע דרך TextEditingController ו-setState מעדכן את הטקסט שמוצג על המסך.

קריאת API ו-JSON

כאשר רוצים לקבל נתונים מהאינטרנט, משתמשים ב-HTTP ופורמטי JSON. בדוגמה הזו נתחבר ל-API ונציג את התוצאה.

הוספת תלות ב-http

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.6

דוגמה לקריאה מ-API

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class ApiPage extends StatefulWidget {
  const ApiPage({Key? key}) : super(key: key);

  @override
  State createState() => _ApiPageState();
}

class _ApiPageState extends State {
  String title = 'טוען...';

  @override
  void initState() {
    super.initState();
    fetchPost();
  }

  Future fetchPost() async {
    final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
    final response = await http.get(url);
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      setState(() {
        title = data['title'];
      });
    } else {
      setState(() {
        title = 'שגיאה בטעינת הנתונים';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('API Example')),
      body: Center(child: Text(title)),
    );
  }
}

השימוש ב-jsonDecode ממיר מחרוזת JSON למבנה Dart קל לשימוש.

Flutter Web ו-JS

Flutter Web מאפשר להריץ את האפליקציה בדפדפן. אפשר גם לשלב JavaScript ולהשתמש ביכולות דפדפן נוספות.

להלן שתי דרכים נפוצות:

  1. להטמיע קובץ JavaScript בדף HTML של web.
  2. להשתמש ב-dart:js או package:js כדי לקרוא ל-JS מתוך Dart.

דוגמה פשוטה ל-JS ב-web/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Flutter Web</title>
    <script>
      function sayHello(name) {
        return 'שלום, ' + name + '!';
      }
    </script>
  </head>
  <body>
    <script src="main.dart.js"></script>
  </body>
</html>

קריאה ל-JS מתוך Dart

import 'dart:js' as js;

void callJs() {
  final result = js.context.callMethod('sayHello', ['יוסף']);
  print(result); // שלום, יוסף!
}

זה שימושי כאשר רוצים לנצל פונקציות דפדפן ספציפיות או ספריות JS קיימות.

JavaScript להסבר כללי

function greet(name) {
  return `שלום ${name}`;
}

console.log(greet('דנה'));

אם אתה מגיע ל-JS בפעם הראשונה, חשוב להבין שזה שפת סקריפט שמשמשת בעיקר בדפדפן וב-Node.js. בפלוטר Web רוב הקוד ב-Dart, אבל ניתן לשלב JS כאשר יש צורך.

Assets וקבצים סטטיים

קבצים סטטיים כמו תמונות, קבצי JSON או פונטים צריכים להירשם ב-pubspec.yaml.

דוגמה לרישום תמונות

flutter:
  assets:
    - assets/images/logo.png
    - assets/data/sample.json

שימוש בתמונה בקוד

Image.asset(
  'assets/images/logo.png',
  width: 120,
  height: 120,
)

נושאים מתקדמים

אדריכלות קוד

כשמסתבכים, הפרד את הקוד לתיקיות:

  • lib/screens/ - מסכים.
  • lib/widgets/ - רכיבים קטנים שניתנים לשימוש חוזר.
  • lib/models/ - מבני נתונים.
  • lib/services/ - חיבור ל-API ולוגיקה עסקית.

State Management

כשאפליקציה גדלה, כדאי להשתמש בפתרונות כמו Provider, Riverpod, Bloc או GetX כדי לנהל מצב במבנים גדולים.

אנימציות בסיסיות

class FadeExample extends StatefulWidget {
  const FadeExample({Key? key}) : super(key: key);

  @override
  State createState() => _FadeExampleState();
}

class _FadeExampleState extends State {
  bool visible = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AnimatedOpacity')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedOpacity(
              opacity: visible ? 1 : 0.2,
              duration: const Duration(milliseconds: 500),
              child: const FlutterLogo(size: 120),
            ),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  visible = !visible;
                });
              },
              child: const Text('החלף מראה'),
            ),
          ],
        ),
      ),
    );
  }
}

שימוש ב-Firebase

נושא גדול, אך חשוב לדעת:

  • התקן את firebase_core ואת התוספים המתאימים.
  • אתחל את Firebase ב-main().
  • השתמש ב-Firestore, Authentication או Storage לפי הצורך.

בעיקרון, גם כאן מדובר בחיבור ל-API חיצוני, וזה נושא דומה לקריאת JSON ו-HttP.

עקרונות להבנת קוד חדש בפלוטר

1. קרא את ה-build()

הפונקציה build() מייצרת את הממשק. היא משתמשת ב-Widgets, ותמיד מחזירה Widget גדול יותר שמכיל את כל המסך.

2. מצא את ה-Widgets הראשיים

חפש Scaffold, AppBar, Column, Row, Text, Image ו-ListView. אלה הרכיבים שמרכיבים את המסך.

3. הפרד קוד לרכיבים

אם מסך ארוך וקשה להבנה, חלק אותו ל-Widgets קטנים עם שמות ברורים. זה הופך כל קוד לקריא יותר.

4. הפשט את הלוגיקה מחוץ ל-UI

שמור חישובים, קריאות API וטיפול בנתונים בקבצים נפרדים ולא בתוך הפונקציה build().

5. נסה לשכתב קוד בהבנה

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

טיפ חשוב: אם אתה רואה Widget שאינך מכיר, חפש את שמו באינטרנט או ב-API של Flutter. רוב ה-Widgets הם פשוטים וניתן להבין אותם על ידי קריאת שמם וחיפוש קצר.

סיכום

במדריך הזה למדנו את היסודות של Flutter ו-Dart, כיצד ליצור מסכים, לנהל מצב, לקרוא API ואת הדרך לשלב JavaScript בפלטפורמת ה-Web.

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