一、特定于平台的代码
在构建跨平台应用程序时,您希望跨平台充用尽可能的代码。但是还,可能会出现代码因操作系统不同而不同的情况。这需要通过声明平台来单独实现。
在React Native中,将使用以下实现:
// React Native
if (Platform.OS === 'ios') {
return 'iOS';
} else if (Platform.OS === 'android') {
return 'android';
} else {
return 'not recognised';
}
在Flutter中,使用以下实现:
final platform = Theme.of(context).platform;
if (platform == TargetPlatform.iOS) {
return 'iOS';
}
if (platform == TargetPlatform.android) {
return 'android';
}
if (platform == TargetPlatform.fuchsia) {
return 'fuchsia';
}
return 'not recognized';
二、调试
2.1、我可以使用哪些工具在Flutter中调试我的应用程序?
使用DevTools套件调试 Flutter 或 Dart 应用程序。
DevTools包括对分析、检查堆、检查小部件树、日志记录诊断、调试、观察执行的代行、调试内存泄口和内存碎片支持。用眼更多信息,请参阅 DevTools文档。
如果您使用的是 IDE,则可以使用 IDE 的调试器调试您的应用程序。
2.2、如何执行热重载?
Flutter的Stateful Hot Reload功能可帮助您快速轻松进行实验、构建UI、添加功能和修复错误。无需在每次进行更改时都重新编译您的应用程序,您可以立即热重新加载您的应用程序。该应用程序会更新以反映您的更改,并保留该应用程序的当前状态。
在React Native中,iOS模拟器的快捷键是⌘R,在Android模拟器上点击R两次。
在Flutter中,如果你使用的是IntelliJ IDE或Android Studio,你可以选择Save All (⌘s/ctrl-s),或者你可以点击工具栏上的Hot Reload按钮。如果你谁用flutter run在命令行运行应用程序,请在终端窗口中输入r。您还可以通过在终端窗口中输入R来执行完全重启。
2.3、如何访问应用内的开发者菜单?
在React Native中,可以通过快捷键来访问您的设备开发者菜单:⌘D 用于 iOS 模拟器或 ⌘M 用于 Android 模拟器。
在Flutter中,如果您使用的是IDE,则可以使用IDE工具。如果您使用flutter run启动您的应用程序,您还可以通过在终端窗口输入h或输入以下快捷键方式来访问菜单:
| 行动 | 终端快捷方式 | 调试函数和属性 |
|---|---|---|
| 应用程序的小部件层次结构 | w | debugDumpApp() |
| 应用程序的渲染树 | t | debugDumpRenderTree() |
| 图层 | L | debugDumpLayerTree() |
| 辅助功能 | S(遍历顺序)或 U(逆命中测试顺序) | debugDumpSemantics() |
| 切换小部件检查器 | i | 小部件应用程序。showWidgetInspectorOverride |
| 切换构造线的显示 | p | debugPaintSizeEnabled |
| 模拟不同的操作系统 | o | 默认目标平台 |
| 显示性能叠加 | P | 小部件应用程序。显示性能叠加层 |
| 将屏幕截图保存到 flutter 中。PNG | s | |
| 退出 | q |
三、动画
精心设计的动画使UI感觉直观,有助于完善应用程序的外观和感觉,并改善用户体验。Flutter的动画支持可以轻松实现简单和复杂的动画。Flutter SDK包含许多标准运动效果的Material Design小部件,您可以轻松自定义这些效果以个性化您的应用程序。
在React Native中,Animated API用于创建动画。
在Flutter中,使用Animation类和AnimationController类。Animation是一个抽象类,它了解其当前值及其状态(已完成或已删除)。该类AnimationController允许您向前或向后播放动画,或听智慧动画并将动画设置为特定值以自定义动作。
3.1、如何添加简单的淡入动画?
在下面的Reactive Native示例中,动画组件FadeInView是使用Animated API创建的。定义了初始不透明状态、最终状态和过渡发生的持续时间。在Animated组件内部添加动画组件,将不透明度状态fadeAnim映射到我们要设置动画的Text组件的不透明度,然后调用start()调用以启动动画。
// React Native
class FadeInView extends React.Component {
state = {
fadeAnim: new Animated.value(0) // Initial value for opacity: 0
};
componentDidMount() {
Animated.timing(this.state.fadeAnim, {
toValue: 1,
duration: 10000,
}).start();
}
render() {
return (
<Animated.View style={{...this.props.style, opacity: this.state.fadeAnim }} >
{this.props.children}
</Animated.View>
);
}
}
...
<FadeInView>
<Text> Fading in </Text>
<FadeInView>
...
要在Flutter中创建想通过的动画,请创建一个名为controller的AnimationController的对象并指定持续是时间。默认情况下AnimationController在给定的持续时间内线性生成范围从0.0到1.0的值。每当运行您的应用程序的设备准备好显示新帧时,动画控制器就会生成一个新值。通常,此速率约为每秒60个值。
在定义AnimationController时,必须传入一个vsync对象。vsync的存在可以防止屏幕外动画消耗不必要的资源。您可以通过将TickerProviderStateMixin添加到类定义来将有状态对象用作vsync.AnimationController需要一个TickerProvider,它是使用构造函数上的vsync参数配置的。
Tween描述开始值和结束值之间的插值或从输入范围到输入范围的映射。要将Tween对象与动画一起使用,请调用Tween对象的animate()方法并将它传递给要修改的Animation对象。
对于此示例,使用了FadeTransitioon小部件并将不透明度属性映射到动画对象。
要启动动画,请使用controller.forward()。其他操作也可以使用控制器执行,例如fling()或repeat().对于此事例,FlutterLogo小部件用于FadeTransition小部件内。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const Center(child: LogoFade(),));
}
class LogoFade extends StatefulWidget {
const LogoFade({Key? key}) : super(key: key);
@override
_LogoFadeState createState() => _LogoFadeState();
}
class _LogoFadeState extends State<LogoFade> with SingleTickerProviderStateMixin{
late Animation<double> animation;
late AnimationController controller;
@override
void 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();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: animation,
child: const SizedBox(
height: 300.0,
width: 300.0,
child: FlutterLogo(),
),
);
}
}
- Android
- iOS
3.2、如何为卡片添加滑动动画?
在React Native中,PanResponder或第三方库用于滑动动画。
在Flutter中,要添加滑动动画,请使用Dismissible小部件并嵌套小部件。
return Dismissible(
key: Key(widget.key.toString()),
onDismissed: (dismissDirection) {
cards.removeLast();
},
child: Container(
// ...
),
);
- Android
-iOS
四、React Native和Flutter widget等效组件
下表列出了常用的React Native组件映射到相应的Flutter widget和常用的widgget属性。
| React Native Component | Flutter Widget | Description |
|---|---|---|
Button | ElevatedButton | A basic raised button. |
| onPressed [required] | The callback when the button is tapped or otherwise activated. | |
| Child | The button’s label. | |
Button | TextButton | A basic flat button. |
| onPressed [required] | The callback when the button is tapped or otherwise activated. | |
| Child | The button’s label. | |
ScrollView | ListView | A scrollable list of widgets arranged linearly. |
| children | ( [ ]) List of child widgets to display. | |
| controller | [ ScrollController ] An object that can be used to control a scrollable widget. | |
| itemExtent | [ double ] If non-null, forces the children to have the given extent in the scroll direction. | |
| scroll Direction | [ Axis ] The axis along which the scroll view scrolls. | |
FlatList | ListView.builder | The constructor for a linear array of widgets that are created on demand. |
| itemBuilder [required] | [IndexedWidgetBuilder] helps in building the children on demand. This callback is called only with indices greater than or equal to zero and less than the itemCount. | |
| itemCount | [ int ] improves the ability of the ListView to estimate the maximum scroll extent. | |
Image | Image | A widget that displays an image. |
| image [required] | The image to display. | |
| Image. asset | Several constructors are provided for the various ways that an image can be specified. | |
| width, height, color, alignment | The style and layout for the image. | |
| fit | Inscribing the image into the space allocated during layout. | |
Modal | ModalRoute | A route that blocks interaction with previous routes. |
| animation | The animation that drives the route’s transition and the previous route’s forward transition. | |
ActivityIndicator | CircularProgressIndicator | A widget that shows progress along a circle. |
| strokeWidth | The width of the line used to draw the circle. | |
| backgroundColor | The progress indicator’s background color. The current theme’s ThemeData.backgroundColor by default. | |
ActivityIndicator | LinearProgressIndicator | A widget that shows progress along a line. |
| value | The value of this progress indicator. | |
RefreshControl | RefreshIndicator | A widget that supports the Material “swipe to refresh” idiom. |
| color | The progress indicator’s foreground color. | |
| onRefresh | A function that’s called when a user drags the refresh indicator far enough to demonstrate that they want the app to refresh. | |
View | Container | A widget that surrounds a child widget. |
View | Column | A widget that displays its children in a vertical array. |
View | Row | A widget that displays its children in a horizontal array. |
View | Center | A widget that centers its child within itself. |
View | Padding | A widget that insets its child by the given padding. |
| padding [required] | [ EdgeInsets ] The amount of space to inset the child. | |
TouchableOpacity | GestureDetector | A widget that detects gestures. |
| onTap | A callback when a tap occurs. | |
| onDoubleTap | A callback when a tap occurs at the same location twice in quick succession. | |
TextInput | TextInput | The interface to the system’s text input control. |
| controller | [ TextEditingController ] used to access and modify text. | |
Text | Text | The Text widget that displays a string of text with a single style. |
| data | [ String ] The text to display. | |
| textDirection | [ TextAlign ] The direction in which the text flows. | |
Switch | Switch | A material design switch. |
| value [required] | [ boolean ] Whether this switch is on or off. | |
| onChanged [required] | [ callback ] Called when the user toggles the switch on or off. | |
Slider | Slider | Used to select from a range of values. |
| value [required] | [ double ] The current value of the slider. | |
| onChanged [required] | Called when the user selects a new value for the slider. |