android开发者可视组件,Android 开发者的 Flutter 指南 — View

View 在 Flutter 中对应什么?

对应的是 Widget,一种声明和构建 UI 的方式。

特点

Widget 仅存在于每一帧之间。当 Widget 或其状态需要改变刷新时,都会重新创建实例以生成新的 Widget 实例树;

不可变,轻量级。不可变是轻量级的部分原因,Widget 不是视图,也不绘制,仅对实际视图中的对象进行描述;

灵活且富有表现力的设计语言。 可以实现任何设计语言,如遵循 Material Design 设计标准且支持所有平台的 Material 组件库;类似 iOS 设计风格的 Cupertino widgets 等。

如何更新 Widget ?

Widget 本身不可变且不能直接更新,只能通过修改 Widget 的状态来达到效果(间接更新:重新构建需要改变的 Widget 以替代原来的)。

由此引申出:

StatelessWidget:无状态,如显示只加载一次的 Logo。

StatefulWidget:有状态,如时常请求网络数据更新页面。

不同点:

StatefulWidget 含有一个可跨帧存取数据的 State 对象。

Widget 可变化,则是有状态的。但子 Widget 是有状态的,其父 Widget 仍可以是 StatelessWidget 。

如何布局 Widget ?

通过 Widget 树实现。

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("Sample App"),

),

body: Center(

child: MaterialButton(

onPressed: () {},

child: Text('Hello'),

padding: EdgeInsets.only(left: 10.0, right: 10.0),

),

),

);

}

可在 Flutter 提供的 Widget 目录 查看相关布局。

如何从布局中移除或添加组件 ?

Flutter 没有类似 addChild() 这种方法,但可通过控制 boolean 类型的标志,来创建显示不同 Widget。

import 'package:flutter/material.dart';

void main() {

runApp(SampleApp());

}

class SampleApp extends StatelessWidget {

// This widget is the root of your application.

@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 {

// Default value for toggle

bool toggle = true;

void _toggle() {

setState(() {

toggle = !toggle;

});

}

_getToggleChild() {

if (toggle) {

return Text('Toggle One');

} else {

return MaterialButton(onPressed: () {}, child: Text('Toggle Two'));

}

}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("Sample App"),

),

body: Center(

child: _getToggleChild(),

),

floatingActionButton: FloatingActionButton(

onPressed: _toggle,

tooltip: 'Update Text',

child: Icon(Icons.update),

),

);

}

}

如何让 Widget 产生动画 ?

通过 animation 库中的动画 Widget 包裹 Widget 。

使用 Animation 子类 AnimationController 控制动画 pause、seek、stop 、reverse 。

淡入淡出动画举例:

import 'package:flutter/material.dart';

void main() {

runApp(FadeAppTest());

}

class FadeAppTest extends StatelessWidget {

// This widget is the root of your application.

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Fade Demo',

theme: ThemeData(

primarySwatch: Colors.blue,

),

home: MyFadeTest(title: 'Fade Demo'),

);

}

}

class MyFadeTest extends StatefulWidget {

MyFadeTest({Key key, this.title}) : super(key: key);

final String title;

@override

_MyFadeTest createState() => _MyFadeTest();

}

class _MyFadeTest extends State with TickerProviderStateMixin {

AnimationController controller;

CurvedAnimation curve;

@override

void initState() {

super.initState();

controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this);

curve = CurvedAnimation(parent: controller, curve: Curves.easeIn);

}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(widget.title),

),

body: Center(

child: Container(

child: FadeTransition(

opacity: curve,

child: FlutterLogo(

size: 100.0,

)))),

floatingActionButton: FloatingActionButton(

tooltip: 'Fade',

child: Icon(Icons.brush),

onPressed: () {

controller.forward();

},

),

);

}

}

如何使用 Canvas 绘制 ?

与 Android 拥有类似的 Canvas API,因为都是基于低级渲染引擎 Skia 。

两个相关类:

CustomPaint:

CustomPainter:通过实现自定义的算法来绘制(implements your algorithm to draw to the canvas)。

可到 StackOverflow 查看 Collin 关于签名绘制的回答。

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: DemoApp()));

class DemoApp extends StatelessWidget {

Widget build(BuildContext context) => Scaffold(body: Signature());

}

class Signature extends StatefulWidget {

SignatureState createState() => SignatureState();

}

class SignatureState extends State {

List _points = [];

Widget build(BuildContext context) {

return GestureDetector(

onPanUpdate: (DragUpdateDetails details) {

setState(() {

RenderBox referenceBox = context.findRenderObject();

Offset localPosition =

referenceBox.globalToLocal(details.globalPosition);

_points = List.from(_points)..add(localPosition);

});

},

onPanEnd: (DragEndDetails details) => _points.add(null),

child: CustomPaint(painter: SignaturePainter(_points), size: Size.infinite),

);

}

}

class SignaturePainter extends CustomPainter {

SignaturePainter(this.points);

final List points;

void paint(Canvas canvas, Size size) {

var paint = Paint()

..color = Colors.black

..strokeCap = StrokeCap.round

..strokeWidth = 5.0;

for (int i = 0; i < points.length - 1; i++) {

if (points[i] != null && points[i + 1] != null)

canvas.drawLine(points[i], points[i + 1], paint);

}

}

bool shouldRepaint(SignaturePainter other) => other.points != points;

}

如何自定义 Widget ?

通过组合粒度更小的 Widget ,而非继承。

class CustomButton extends StatelessWidget {

final String label;

CustomButton(this.label);

@override

Widget build(BuildContext context) {

return RaisedButton(onPressed: () {}, child: Text(label));

}

}

@override

Widget build(BuildContext context) {

return Center(

child: CustomButton("Hello"),

);

}

原文给 Android 开发者的 Flutter 指南,参考Android 开发者参考。

此文目的:仅与 Android 对比,尽可能言简意骇的翻译,且不遗漏、不曲解词义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值