- PVSM.RU - https://www.pvsm.ru -
Продолжаем лаконичную интерпретацию официальной документации Flutter [1] в формате «вопрос-ответ». Вот уже 3-я часть, и она в большей степени будет полезна React Native-разработчикам. В данной интерпретации вы можете найти ответы на частые вопросы, а также определить для себя, сколько усилий нужно приложить, чтобы перейти с одного кроссплатформенного фреймворка на другой.
Если этой информации будет недостаточно или у вас есть опыт в нативной разработке под конкретную платформу, то рекомендую заглянуть в другие части:
Flutter. Часть 1. Для Android-разработчиков [2]
Flutter. Часть 2. Для iOS-разработчиков [3]
Flutter. Часть 3. Для разработчиков React Native
Flutter. Часть 4. Для Web-разработчиков
Flutter. Часть 5. Для Xamarin.Forms-разработчиков
Где точка входа?
Функция main()
.
В JavaScript нет предопределённой точки входа, ею может быть любая функция, определённая разработчиком. В Dart это только main()
.
Как делать вывод в консоль?
С помощью функции print()
.
В JavaScript вывод в консоль осуществляется с помощью console.log()
.
print('Hello world!');
Как создавать и присваивать переменные/поля?
Dart поддерживает и динамическую, и строгую типизацию. Поэтому переменные/поля создавать можно в любом удобном вам виде типизации. Присваивание происходит через одинарное =.
В JavaScript строгая типизация не поддерживается.
Подробнее тут. [69]
String name = 'dart'; // Explicitly typed as a string.
var otherName = 'Dart'; // Inferred string.
// Both are acceptable in Dart.
Какое значение у переменной/поля по умолчанию?
null
В JavaScript по умолчанию undefined
.
Подробнее тут. [70]
Как проверять значение на null
или на 0?
С помощью явной проверки ==
.
В JavaScript в рамках проверки if
число 1 или любой non-null
объект будет эквивалентен true
. В Dart только булевое значение true
эквивалентно true
.
var myNull = null;
if (myNull == null) {
print('use "== null" to check null');
}
var zero = 0;
if (zero == 0) {
print('use "== 0" to check zero');
}
Как декларировать функции?
В Dart функции, как и поля, могут быть с динамической или строгой типизацией возвращаемого значения. Динамически типизируемые декларируются просто именем функции и опционально параметрами, а строго типизируемые в начале ещё имеют возвращаемый тип.
В JavaScript функция декларируется ключевым словом function
, далее имя и опционально — параметры.
Подробнее тут. [71]
fn() {
return true;
}
// can also be written as
bool fn() {
return true;
}
Какой аналог у Promise [72]?
Future [73]
Dart, как и JavaScript, поддерживает однопоточное выполнение. Future [73] в Dart по смыслу выполняет те же функции, что и Promise [72] в React Native.
Подробнее тут. [74].
import 'dart:convert';
import 'package:http/http.dart' as http;
class Example {
Future<String> _getIPAddress() {
final url = 'https://httpbin.org/ip';
return http.get(url).then((response) {
String ip = jsonDecode(response.body)['origin'];
return ip;
});
}
}
main() {
final example = new Example();
example
._getIPAddress()
.then((ip) => print(ip))
.catchError((error) => print(error));
}
Какой аналог async
и await
?
async
и await
В JavaScript async-функции возвращают Promise [72], в Dart — Future [73]. await синхронно ожидает результата вызова async-функции.
Подробнее тут. [75]
import 'dart:convert';
import 'package:http/http.dart' as http;
class Example {
Future<String> _getIPAddress() async {
final url = 'https://httpbin.org/ip';
final response = await http.get(url);
String ip = jsonDecode(response.body)['origin'];
return ip;
}
}
main() async {
final example = new Example();
try {
final ip = await example._getIPAddress();
print(ip);
} catch (error) {
print(error);
}
}
Как создать проект приложения на Flutter?
flutter create {projectname}
.
Для создания проекта в React Native используется команда create-react-native-app {projectname}
.
Подробнее тут. [76]
Как запустить приложение?
flutter run
.
Для запуска приложения в React Native используются команды npm run
или yarn run
.
Как импортировать виджеты?
Во Flutter все виджеты разбиты по пакетам, поэтому достаточно импортировать пакет, чтобы использовать его виджеты.
В React Native необходимо импортировать каждый виджет.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/my_widgets.dart';
Как использовать виджеты и вложенность для построения дерева виджетов?
Во Flutter почти всё — виджеты. Даже объект приложения — виджет. Каждый виджет может быть вложенным в родительский. Комбинируя виджеты, вы строите иерархию, которая называется «деревом виджетов». Именно она в дальнейшем превращается в отображение на экране.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text('Hello world'),
),
),
);
}
}
Как создавать переиспользуемые компоненты?
Во Flutter можно создать класс виджета и переиспользовать его. Используемые параметры являются полями класса.
В React Native для изменения параметров переиспользуемого элемента необходимо их пометить как props.
Параметры в конструкторе могут декларироваться двумя способами: обычным перечислением и опциональным, с помощью фигурных скобок {}
. Отличия проявляются при использовании параметров для вызова конструктора.
При обычном перечислении все параметры являются обязательными, и при вызове конструктора нельзя указать, какой конкретно параметр передаётся, т.к. они обусловлены порядком следования.
При опциональном можно использовать любой порядок передачи параметров, но необходимо указать, какой конкретно параметр передаётся или не передавать их вовсе. Чтобы обозначить опциональный параметр как обязательный, нужно использовать аннотацию @required
.
class CustomCard extends StatelessWidget {
CustomCard({@required this.index, @required
this.onPress});
final index;
final Function onPress;
@override
Widget build(BuildContext context) {
return Card(
child: Column(
children: <Widget>[
Text('Card $index'),
FlatButton(
child: const Text('Press'),
onPressed: this.onPress,
),
],
)
);
}
}
...
// Usage
CustomCard(
index: index,
onPress: () {
print('Card $index');
},
)
...
Где начинать писать код?
В {projectname}/lib/main.dart
.
Какая структура файлов в проекте Flutter?
┬
└ projectname
┬
├ android - файлы для Android сборки.
├ build - iOS и Android результаты сборки.
├ ios - файлы для iOS сборки.
├ lib - Dart файлы.
┬
└ src - Contains additional source files.
└ main.dart - точка входа в приложение.
├ test - Файлы тестов.
└ pubspec.yaml - Описание зависимостей и ресурсов приложения.
Аналог package.json файла в React Native.
Где хранить ресурсы и ассеты и как их использовать?
Ссылки на ресурсы и зависимости проекта хранятся в файле pubspec.yaml
. Фактически располагать их можно в любой папке внутри lib
, главное, указать к ним путь в pubspec.yaml
. Использовать их в проекте можно либо с помощью специализированных виджетов, например AssetImage [77], либо напрямую, с помощью AssetBundle [78].
Подробнее тут. [79]
Декларирование ассетов в pubspec.yaml
flutter:
assets:
- assets/my_icon.png
- assets/background.png
Использование в коде
image: AssetImage('assets/background.png'),
Как загружать изображения из сети?
С помощью Image.network [80].
body: Image.network(
'https://flutter.io/images/owl.jpg',
Как подключать сторонние пакеты и плагины?
С помощью dependencies
в pubspec.yaml
.
В React Native для добавления зависимостей используются команды yarn add {package-name}
или npm install --save {package-name}
.
Использование пакетов [81]
Разработка пакетов и плагинов [82]
Популярные плагины для Flutter [83]
dependencies:
flutter:
sdk: flutter
google_sign_in: ^3.0.3
Какой аналог у View [84] контейнера?
Все базовые виджеты для вёрcтки, например Container [85], Column [86], Row [87] и Center [88].
Подробнее тут. [89]
Какой аналог FlatList [90] или SelectionList [91]?
ListView [92]
var data = [ ... ];
ListView.builder(
itemCount: data.length,
itemBuilder: (context, int index) {
return Text(
data[index],
);
},
)
Как использовать Canvas?
С помощью классов CustomPaint [93] и CustomPainter [94].
В React Native нет возможности рисовать с помощью Canvas из коробки. Есть сторонние плагины, например react-native-canvas
.
class MyCanvasPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Colors.amber;
canvas.drawCircle(Offset(100.0, 200.0), 40.0, paint);
Paint paintRect = Paint();
paintRect.color = Colors.lightBlue;
Rect rect = Rect.fromPoints(Offset(150.0, 300.0), Offset(300.0, 400.0));
canvas.drawRect(rect, paintRect);
}
bool shouldRepaint(MyCanvasPainter oldDelegate) => false;
bool shouldRebuildSemantics(MyCanvasPainter oldDelegate) => false;
}
class _MyCanvasState extends State<MyCanvas> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomPaint(
painter: MyCanvasPainter(),
),
);
}
}
Как использовать виджеты для описания свойств вёрстки?
Во Flutter для свойств вёрстки используются специализированные виджеты, например:
Column [86], Row [87], Padding [95], Align [96], Stack [97].
В React Native чаще всего свойства вёрстки можно задать с помощью props
.
Как позиционировать виджеты при вёрстке?
Для абсолютного позиционирования используется виджет Stack [97]. Для относительного — различные виджеты и их комбинации, которые можно найти здесь [89].
Stack(
alignment: const Alignment(0.6, 0.6),
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
'https://avatars3.githubusercontent.com/u/14101776?v=4'),
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text('Flutter'),
),
],
)
Как стилизовать компоненты?
Чаще всего у виджетов есть свойство style
.
В React Native для стилизации используется stylesheets.create
.
var textStyle = TextStyle(fontSize: 32.0, color: Colors.cyan, fontWeight:
FontWeight.w600);
...
Center(
child: Column(
children: <Widget>[
Text(
'Sample text',
style: textStyle,
),
Padding(
padding: EdgeInsets.all(20.0),
child: Icon(Icons.lightbulb_outline,
size: 48.0, color: Colors.redAccent)
),
],
),
)
Как использовать иконки и цвета?
С помощью классов Icons [98] и Colors [99].
В React Native нет поддержки иконок из коробки.
Icons
Icon(Icons.lightbulb_outline, color: Colors.redAccent)
Colors
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
textSelectionColor: Colors.red
),
home: SampleAppPage(),
);
}
}
Как настраивать стилистичекую тему приложения?
С помощью класса ThemeData [100].
В React Native общая тема настривается через stylesheets
.
Пример:
@override
Widget build(BuildContext context) {
return Theme(
data: ThemeData(
primaryColor: Colors.cyan,
brightness: brightness,
),
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
...
...
),
);
}
Как обновлять отображение виджетов?
Используя StatefulWidget [101] и его State [102]. Во Flutter есть 2 вида виджетов: StatelessWidget [103] и StatefulWidget [101]. Они работают одинаково, отличие только в состоянии при рендеринге.
StatelessWidget [103] имеет неизменное состояние. Подойдёт для отображения текста, логотипа и т.д. Т.е. если элемент на экране не должен изменяться за всё время отображения, значит, он вам подходит. Его можно использовать и как контейнер для виджетов с изменяемым состоянием.
StatefulWidget [101] имеет состояние State [102], в котором хранится информация о текущем состоянии. Если вы хотите изменить элемент на экране при выполнении какого-то действия (пришёл ответ с сервера, пользователь нажал на кнопку и т.д.) — это ваш вариант.
1) StatelessWidget — Text
Text(
'I like Flutter!',
style: TextStyle(fontWeight: FontWeight.bold),
);
2) StatefulWidget — при нажатии на кнопку (FloatingActionButton) текст в виджете Text меняется с I Like Flutter на Flutter is Awesome!
import 'package:flutter/material.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// Этот виджет корневой в приложении.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// дефолтный текст
String textToShow = "Мне нравится Flutter";
void _updateText() {
setState(() {
// обновление текста
textToShow = "Flutter крутой!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(child: Text(textToShow)),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Обновить текст',
child: Icon(Icons.update),
),
);
}
}
Как хранить key-value
данные в приложении?
С помощью плагина shared_preferences [104].
В React Native используется AsyncStorage [105].
Подключение зависимости
dependencies:
flutter:
sdk: flutter
shared_preferences: ^0.4.3
Использование
SharedPreferences prefs = await SharedPreferences.getInstance();
_counter = prefs.getInt('counter');
prefs.setInt('counter', ++_counter);
setState(() {
_counter = _counter;
});
Как хранить сложные данные?
С помощью плагинов БД, например, sqflite [106] или hive [107].
Как навигировать между экранами?
Для навигации между экранами используются классы Navigator [108] и Route [109].
В React Native используются StackNavigator [110], TabNavigator [111] и DrawerNavigator [112].
Во Flutter есть два способа навигации:
Navigator [108] может сделать push() [113] или pop() [114] указанному вами маршруту.
void main() {
runApp(CupertinoApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}
Navigator.of(context).pushNamed('/b');
Как использовать tab navigation?
С помощью классов: TabController [115], TabBar [116], Tab [117] и TabBarView [118].
В React Native используются createBottomTabNavigator и TabNavigation [111].
Подробнее тут. [119].
class _NavigationHomePageState extends State<NavigationHomePage> with SingleTickerProviderStateMixin {
TabController controller=TabController(length: 2, vsync: this);
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Material (
child: TabBar(
tabs: <Tab> [
Tab(icon: Icon(Icons.person),)
Tab(icon: Icon(Icons.email),),
],
controller: controller,
),
color: Colors.blue,
),
body: TabBarView(
children: <Widget> [
home.homeScreen(),
tabScreen.tabScreen()
],
controller: controller,
)
);
}
}
Как использовать drawer navigation?
С помощью класса Drawer [120].
В React Native используются createDrawerNavigator и DrawerNavigation [112].
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
child: ListTile(
leading: Icon(Icons.change_history),
title: Text('Screen2'),
onTap: () {
Navigator.of(context).pushNamed('/b');
},
),
elevation: 20.0,
),
appBar: AppBar(
title: Text('Home'),
),
body: Container(),
);
}
Как обрабатывать клик?
Если виджет поддерживает клики, то в onPressed()
. Если нет, то с помощью виджета GestureDetector [121].
В React Native для этого используются PanResponder [122] или Touchable [123].
GestureDetector(
child: Scaffold(
appBar: AppBar(
title: Text('Gestures'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Tap, Long Press, Swipe Horizontally or Vertically '),
],
)
),
),
onTap: () {
print('Tapped');
},
onLongPress: () {
print('Long Pressed');
},
onVerticalDragEnd: (DragEndDetails value) {
print('Swiped Vertically');
},
onHorizontalDragEnd: (DragEndDetails value) {
print('Swiped Horizontally');
},
);
Как получать данные из API запросов?
С помощью http-плагина [124].
В React Native используется fetch API
.
Подключение плагина
dependencies:
flutter:
sdk: flutter
http: <latest_version>
Получение данных
final url = Uri.https('httpbin.org', 'ip');
final httpClient = HttpClient();
_getIPAddress() async {
var request = await httpClient.getUrl(url);
var response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
String ip = jsonDecode(responseBody)['origin'];
setState(() {
_ipAddress = ip;
});
}
Какие виджеты использовать для ввода?
TextField [125] в связке с TextEditingController [126] или TextFormField [127].
В React Native используется TextInput [128].
TextFormField [127] отличается от TextField [125] встроенной валидацией и логикой сохранения значений в поля.
TextField
final TextEditingController _controller = TextEditingController();
...
TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Type something', labelText: 'Text Field '
),
),
RaisedButton(
child: Text('Submit'),
onPressed: () {
showDialog(
context: context,
child: AlertDialog(
title: Text('Alert'),
content: Text('You typed ${_controller.text}'),
),
);
},
),
)
TextFormField
final formKey = GlobalKey<FormState>();
...
Form(
key:formKey,
child: Column(
children: <Widget>[
TextFormField(
validator: (value) => !value.contains('@') ? 'Not a valid email.' : null,
onSaved: (val) => _email = val,
decoration: const InputDecoration(
hintText: 'Enter your email',
labelText: 'Email',
),
),
RaisedButton(
onPressed: _submit,
child: Text('Login'),
),
],
),
)
void _submit() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
showDialog(
context: context,
child: AlertDialog(
title: Text('Alert'),
content: Text('Email: $_email, password: $_password'),
)
);
}
}
Как определить, на какой платформе выполняется код?
С помощью класса поля platform
в Theme [129] или класса Platform [130].
Поле platform
if (Theme.of(context).platform == TargetPlatform.iOS) {
return 'iOS';
} else if (Theme.of(context).platform == TargetPlatform.android) {
return 'android';
} else if (Theme.of(context).platform == TargetPlatform.fuchsia) {
return 'fuchsia';
} else {
return 'not recognised ';
}
Класс Platform
if (Platform.isIOS) {
return 'iOS';
} else if (Platform.isAndroid) {
return 'android';
} else if (Platform.isFuchsia) {
return 'fuchsia';
} else {
return 'not recognised ';
}
Как вызвать нативный платформенный код?
Через MethodChannel [131].
Подробнее тут. [132].
Какие есть инструменты для отладки приложения?
DevTools [133].
Как сделать hot reload
?
Если приложение запускалось из IntelliJ IDE или Android Studio, то сочетанием ⌘s/ctrl-s
или нажатием на иконку hot reload
. Если запускалось из терминала, то вводом буквы r
.
В React Native для iOS-эмуляторов используется сочетание ⌘R/Ctrl+R
, для Android — двойное R
.
Как получить доступ к меню разработчика в приложении?
Если запуск был из IDE, то с помощью инструментов IDE. Если из консоли, то с помощью ввода h.
В React Native используются ⌘D/Ctrl+D
для iOS эмуляторов и ⌘M/Ctrl+M
для Android.
Полный список команд
Действие | Команда в терминале | Функции и поля |
Иерархия виджетов | w | debugDumpApp() |
Дерево рендеринга | t | debugDumpRenderTree() |
Слои | L | debugDumpLayerTree() |
Accessibility | S (traversal order) or U (inverse hit test order) | debugDumpSemantics() |
Инспектор виджетов | i | WidgetsApp.showWidgetInspectorOverride |
Отображение линий построения | p | debugPaintSizeEnabled |
Симуляция разных ОС | o | defaultTargetPlatform |
Перфоманс | P | WidgetsApp. showPerformanceOverlay |
Скриншот flutter.png | s | |
Закрытие приложения | q |
Что используется для анимации?
Animation [134] и AnimationController [135].
В React Native используется Animation API
.
Подробнее тут. [136]
Как добавить простую fade-in
анимацию?
С помощью FadeTransition [137].
import 'package:flutter/material.dart';
void main() {
runApp(Center(child: LogoFade()));
}
class LogoFade extends StatefulWidget {
_LogoFadeState createState() => _LogoFadeState();
}
class _LogoFadeState extends State<LogoFade> with TickerProviderStateMixin {
Animation animation;
AnimationController controller;
initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 3000), vsync: this);
final CurvedAnimation curve =
CurvedAnimation(parent: controller, curve: Curves.easeIn);
animation = Tween(begin: 0.0, end: 1.0).animate(curve);
controller.forward();
}
Widget build(BuildContext context) {
return FadeTransition(
opacity: animation,
child: Container(
height: 300.0,
width: 300.0,
child: FlutterLogo(),
),
);
}
dispose() {
controller.dispose();
super.dispose();
}
}
Как добавить анимацию смахивания элементам списка?
С помощью Dismissible [138].
child: Dismissible(
key: key,
onDismissed: (DismissDirection dir) {
cards.removeLast();
},
child: Container(
...
),
),
Какие эквиваленты есть во Flutter по сравнению с React Native?
React Native | Flutter |
Button [139] | RaisedButton [140] |
Button [139] | FlatButton [141] |
ScrollView [142] | ListView [92] |
FlatList [143] | ListView.builder() [144] |
Image [145] | Image [146] |
Modal [147] | ModalRoute [148] |
ActivityIndicator [149] | CircularProgressIndicator [150] |
ActivityIndicator [149] | LinearProgressIndicator [151] |
RefreshControl [152] | RefreshIndicator [153] |
View [154] | Container [85] |
View [154] | Column [86] |
View [154] | Row [87] |
View [154] | Center [88] |
View [154] | Padding [95] |
TouchableOpacity [155] | GestureDetector [121] |
TextInput [156] | TextInput [157] |
Text [158] | Text [159] |
Switch [160] | Switch [161] |
Slider [162] | Slider [163] |
Как получить доступ к GPS?
С помощью плагина geolocator [164].
Как получить доступ к камере?
С помощью плагина image_picker [165].
Как авторизоваться через Facebook?
С помощью плагина flutter_facebook_login [166].
Как использовать Firebase?
Firebase поддерживает Flutter first party plugins [167]:
Вот, пожалуй, ответы на основные вопросы. Надеюсь, моя интерпретация была для вас полезна, и если вы ещё не пишите на Flutter, то хотя бы задумались об этом. А это значит, что в полку Flutter разработчиков, возможно, будет прибавление, и мы вместе будем делать мир лучше через призму разработанных удобных и быстрых приложений! Да не сломает React ваш Native!
Автор: Дмитрий Васильев
Источник [176]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/343821
Ссылки в тексте:
[1] официальной документации Flutter: https://flutter.dev/docs/get-started/flutter-for/react-native-devs
[2] Flutter. Часть 1. Для Android-разработчиков: https://habr.com/ru/company/funcorp/blog/442432/
[3] Flutter. Часть 2. Для iOS-разработчиков: https://habr.com/ru/company/funcorp/blog/477182/
[4] Немного про Dart: #dart
[5] Где точка входа?: #entry_point
[6] Как делать вывод в консоль?: #concole
[7] Как создавать и присваивать переменные/поля?: #fields
[8] Какое значение у переменной/поля по умолчанию?: #default_value
[9] Как проверять значение на null или на 0?: #null_check
[10] Как декларировать функции?: #functions
[11] Какой аналог у Promise?: #promise
[12] Какой аналог async и await?: #async_await
[13] Основы: #basic
[14] Как создать проект приложения на Flutter?: #project
[15] Как запустить приложение?: #run
[16] Как импортировать виджеты?: #import
[17] Как использовать виджеты и вложенность для построения дерева виджетов?: #widget_tree
[18] Как создавать переиспользуемые компоненты?: #reusable
[19] Структура проекта и ресурсы: #project_structure
[20] Где начинать писать код?: #code_start
[21] Какая структура файлов в проекте Flutter?: #files_structure
[22] Где хранить ресурсы и ассеты и как их использовать?: #resources
[23] Как загружать изображения из сети?: #network_images
[24] Как подключать сторонние пакеты и плагины?: #dependencies
[25] Views: #views
[26] Какой аналог у View контейнера?: #view_analog
[27] Какой аналог FlatList или SelectionList?: #flatlist_selectionlist
[28] Как использовать Canvas?: #canvas
[29] Layouts: #layouts
[30] Как использовать виджеты для описания свойств вёрстки?: #widgets_layout
[31] Как позиционировать виджеты при вёрстке?: #widgets_positions
[32] Стилизация: #styles
[33] Как стилизовать компоненты?: #components_style
[34] Как использовать иконки и цвета?: #colors_and_icons
[35] Как настраивать стилистичекую тему приложения?: #theme
[36] State management: #state_management
[37] Как обновлять отображение виджетов?: #widgets_update
[38] Локальное хранилище: #storage
[39] Как хранить key-value данные в приложении?: #preferences
[40] Как хранить сложные данные?: #db
[41] Навигация: #navigation
[42] Как навигировать между экранами?: #screens
[43] Как использовать tab navigation?: #tab_navigation
[44] Как использовать drawer navigation?: #drawer_navigation
[45] Жесты и обработка touch event: #gestures
[46] Как обрабатывать клик?: #on_click
[47] HTTP-запросы: #http
[48] Как получать данные из API запросов?: #api
[49] Форма ввода: #input
[50] Какие виджеты использовать для ввода?: #input_widgets
[51] Platform-specific code: #platform_specific
[52] Как определить, на какой платформе выполняется код?: #platform
[53] Как вызвать нативный платформенный код?: #native
[54] Отладка: #debug
[55] Какие есть инструменты для отладки приложения?: #instruments
[56] Как сделать hot reload?: #hot_reload
[57] Как получить доступ к меню разработчика в приложении?: #developer_menu
[58] Анимация: #animation
[59] Что используется для анимации?: #animation_usage
[60] Как добавить простую fade-in анимацию?: #fade_in
[61] Как добавить анимацию смахивания элементам списка?: #swipe_animation
[62] Эквиваленты компонентов: #components
[63] Какие эквиваленты есть во Flutter по сравнению с React Native?: #equivalents
[64] Плагины Flutter: #plugins
[65] Как получить доступ к GPS?: #gps
[66] Как получить доступ к камере?: #camera
[67] Как авторизоваться через Facebook?: #facebook
[68] Как использовать Firebase?: #firebase
[69] Подробнее тут.: https://dart.dev/guides/language/sound-dart
[70] Подробнее тут.: https://dart.dev/guides/language/language-tour#variables
[71] Подробнее тут.: https://dart.dev/guides/language/language-tour#functions
[72] Promise: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise
[73] Future: https://api.dart.dev/stable/2.7.0/dart-async/Future-class.html
[74] Подробнее тут.: https://dart.dev/codelabs/async-await
[75] Подробнее тут.: https://dart.dev/guides/language/language-tour#asynchrony-support
[76] Подробнее тут.: https://flutter.dev/docs/get-started/install
[77] AssetImage: https://api.flutter.dev/flutter/painting/AssetImage-class.html
[78] AssetBundle: https://api.flutter.dev/flutter/services/AssetBundle-class.html
[79] Подробнее тут.: https://flutter.dev/docs/development/ui/assets-and-images
[80] Image.network: https://api.flutter.dev/flutter/widgets/Image/Image.network.html
[81] Использование пакетов: https://flutter.dev/docs/development/packages-and-plugins/using-packages
[82] Разработка пакетов и плагинов: https://flutter.dev/docs/development/packages-and-plugins/developing-packages
[83] Популярные плагины для Flutter: https://pub.dev/flutter/packages
[84] View: https://facebook.github.io/react-native/docs/view
[85] Container: https://api.flutter.dev/flutter/widgets/Container-class.html
[86] Column: https://api.flutter.dev/flutter/widgets/Column-class.html
[87] Row: https://api.flutter.dev/flutter/widgets/Row-class.html
[88] Center: https://api.flutter.dev/flutter/widgets/Center-class.html
[89] Подробнее тут.: https://flutter.dev/docs/development/ui/widgets/layout
[90] FlatList: https://facebook.github.io/react-native/docs/flatlist
[91] SelectionList: https://facebook.github.io/react-native/docs/sectionlist
[92] ListView: https://api.flutter.dev/flutter/widgets/ListView-class.html
[93] CustomPaint: https://api.flutter.dev/flutter/widgets/CustomPaint-class.html
[94] CustomPainter: https://api.flutter.dev/flutter/rendering/CustomPainter-class.html
[95] Padding: https://api.flutter.dev/flutter/widgets/Padding-class.html
[96] Align: https://api.flutter.dev/flutter/widgets/Align-class.html
[97] Stack: https://api.flutter.dev/flutter/widgets/Stack-class.html
[98] Icons: https://api.flutter.dev/flutter/material/Icons-class.html
[99] Colors: https://api.flutter.dev/flutter/material/Colors-class.html.
[100] ThemeData: https://api.flutter.dev/flutter/material/ThemeData-class.html
[101] StatefulWidget: https://docs.flutter.io/flutter/widgets/StatefulWidget-class.html
[102] State: https://docs.flutter.io/flutter/widgets/State-class.html
[103] StatelessWidget: https://docs.flutter.io/flutter/widgets/StatelessWidget-class.html
[104] shared_preferences: https://pub.dev/packages/shared_preferences
[105] AsyncStorage: https://facebook.github.io/react-native/docs/asyncstorage
[106] sqflite: https://pub.dev/packages/sqflite
[107] hive: https://pub.dev/packages/hive
[108] Navigator: https://docs.flutter.io/flutter/widgets/Navigator-class.html
[109] Route: https://docs.flutter.io/flutter/widgets/Route-class.html
[110] StackNavigator: https://reactnavigation.org/docs/en/1.x/stack-navigator.html
[111] TabNavigator: https://reactnavigation.org/docs/en/next/tab-based-navigation.html#docsNav
[112] DrawerNavigator: https://reactnavigation.org/docs/en/next/drawer-based-navigation.html#docsNav
[113] push(): https://docs.flutter.io/flutter/widgets/Navigator/push.html
[114] pop(): https://docs.flutter.io/flutter/widgets/Navigator/pop.html
[115] TabController: https://api.flutter.dev/flutter/material/TabController-class.html
[116] TabBar: https://api.flutter.dev/flutter/material/TabBar-class.html
[117] Tab: https://api.flutter.dev/flutter/material/Tab-class.html
[118] TabBarView: https://api.flutter.dev/flutter/material/TabBarView-class.html
[119] Подробнее тут.: https://flutter.dev/docs/cookbook/design/tabs
[120] Drawer: https://api.flutter.dev/flutter/material/Drawer-class.html
[121] GestureDetector: https://api.flutter.dev/flutter/widgets/GestureDetector-class.html
[122] PanResponder: https://facebook.github.io/react-native/docs/panresponder
[123] Touchable: https://facebook.github.io/react-native/docs/handling-touches#touchables
[124] http-плагина: https://pub.dev/packages/http
[125] TextField: https://api.flutter.dev/flutter/material/TextField-class.html
[126] TextEditingController: https://api.flutter.dev/flutter/widgets/TextEditingController-class.html
[127] TextFormField: https://api.flutter.dev/flutter/material/TextFormField-class.html
[128] TextInput: https://facebook.github.io/react-native/docs/textinput
[129] Theme: https://api.flutter.dev/flutter/material/Theme-class.html
[130] Platform: https://api.flutter.dev/flutter/package-platform_platform/Platform-class.html
[131] MethodChannel: https://api.flutter.dev/flutter/services/MethodChannel-class.html
[132] Подробнее тут.: https://flutter.dev/docs/development/platform-integration/platform-channels
[133] DevTools: https://flutter.dev/docs/development/tools/devtools
[134] Animation: https://api.flutter.dev/flutter/animation/Animation-class.html
[135] AnimationController: https://api.flutter.dev/flutter/animation/AnimationController-class.html
[136] Подробнее тут.: https://flutter.dev/docs/development/ui/animations
[137] FadeTransition: https://api.flutter.dev/flutter/widgets/FadeTransition-class.html
[138] Dismissible: https://api.flutter.dev/flutter/widgets/Dismissible-class.html
[139] Button: https://facebook.github.io/react-native/docs/button.html
[140] RaisedButton: https://api.flutter.dev/flutter/material/RaisedButton-class.html
[141] FlatButton: https://api.flutter.dev/flutter/material/FlatButton-class.html
[142] ScrollView: https://facebook.github.io/react-native/docs/scrollview.html
[143] FlatList: https://facebook.github.io/react-native/docs/flatlist.html
[144] ListView.builder(): https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html
[145] Image: https://facebook.github.io/react-native/docs/image.html
[146] Image: https://api.flutter.dev/flutter/widgets/Image-class.html
[147] Modal: https://facebook.github.io/react-native/docs/modal.html
[148] ModalRoute: https://api.flutter.dev/flutter/widgets/ModalRoute-class.html
[149] ActivityIndicator: https://facebook.github.io/react-native/docs/activityindicator.html
[150] CircularProgressIndicator: https://api.flutter.dev/flutter/material/CircularProgressIndicator-class.html
[151] LinearProgressIndicator: https://api.flutter.dev/flutter/material/LinearProgressIndicator-class.html
[152] RefreshControl: https://facebook.github.io/react-native/docs/refreshcontrol.html
[153] RefreshIndicator: https://api.flutter.dev/flutter/material/RefreshIndicator-class.html
[154] View: https://facebook.github.io/react-native/docs/view.html
[155] TouchableOpacity: https://facebook.github.io/react-native/docs/touchableopacity.html
[156] TextInput: https://api.flutter.dev/flutter/services/TextInput-class.html
[157] TextInput: https://facebook.github.io/react-native/docs/textinput.html
[158] Text: https://facebook.github.io/react-native/docs/text.html
[159] Text: https://api.flutter.dev/flutter/widgets/Text-class.html
[160] Switch: https://facebook.github.io/react-native/docs/switch.html
[161] Switch: https://api.flutter.dev/flutter/material/Switch-class.html
[162] Slider: https://facebook.github.io/react-native/docs/slider.html
[163] Slider: https://api.flutter.dev/flutter/material/Slider-class.html
[164] geolocator: https://pub.dartlang.org/packages/geolocator
[165] image_picker: https://pub.dartlang.org/packages/image_picker
[166] flutter_facebook_login: https://pub.dartlang.org/packages/flutter_facebook_login
[167] Flutter first party plugins: https://pub.dartlang.org/flutter/packages?q=firebase
[168] firebase_admob: https://pub.dartlang.org/packages/firebase_admob
[169] firebase_analytics: https://pub.dartlang.org/packages/firebase_analytics
[170] firebase_auth: https://pub.dartlang.org/packages/firebase_auth
[171] firebase_database: https://pub.dartlang.org/packages/firebase_database
[172] firebase_storage: https://pub.dartlang.org/packages/firebase_storage
[173] firebase_messaging: https://pub.dartlang.org/packages/firebase_messaging
[174] flutter_firebase_ui: https://pub.dartlang.org/packages/flutter_firebase_ui
[175] cloud_firestore: https://pub.dartlang.org/packages/cloud_firestore
[176] Источник: https://habr.com/ru/post/484284/?utm_source=habrahabr&utm_medium=rss&utm_campaign=484284
Нажмите здесь для печати.