Flutter开发者

自定义View概述

2018-10-15

上期回顾

在前面的文章中我们学习了ExpansionPanelList的用法,使用ExpansionPanelList可以很轻松的实现可展开列表的效果,在文章的最后依然给大家留下了个小问题,实现如下效果。

在前面已经提到了,使用ExpansionPanelList.radio()每次只能打开一个Item,当有一个item处于打开状态时在点击其他item就没有效果了,所以在这里我们依然要借助于ExpansionPanelList来实现,其实实现起来还是很简单的,只不过是记录下打开的position而已。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: ExpansionPanelListDemo(),
));
}

class ExpansionPanelListDemo extends StatefulWidget {
@override
_ExpansionPanelListDemoState createState() => _ExpansionPanelListDemoState();
}

class _ExpansionPanelListDemoState extends State<ExpansionPanelListDemo> {
var currentPanelIndex = -1;
List<int> mList;

_ExpansionPanelListDemoState() {
mList = new List();
for (int i = 0; i < 10; i++) {
mList.add(i);
}
}


_setCurrentIndex(int index) {
setState(() {

if(currentPanelIndex==index){
index=-1;
}
currentPanelIndex = index;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ExpansionPanelList"),
),
body: SingleChildScrollView(child: ExpansionPanelList(
children: mList.map((index) {
return new ExpansionPanel(
headerBuilder: (context, isExpanded) {
return new ListTile(
title: new Text('我是第$index个标题'),
);
},
body: new Padding(
padding: EdgeInsets.symmetric(horizontal: 5.0),
child: Container(height: 100.0,
color: Colors.blue,
alignment: Alignment.center,
child:Icon(Icons.security,size: 35.0,),),
),
isExpanded: currentPanelIndex == index,
);
}).toList(),

expansionCallback: (index, bol) {
_setCurrentIndex(index);
},

),));
}
}

有问题的小伙伴可以在文章最下面留言哦

Flutter中的自定义View

在往期文章中我们花了很多篇文章来学习Flutter Widget 的用法,在Flutter中Widget有很多,我不肯能每个都给大家介绍到,但是我基本上把常用的都给大家介绍到了(个人认为^_^)。

当然,如果你觉得我有哪些你特别想要了解而我没有涉及的,可以在文章下面或者公众号留言,我会抽时间安排的。

但是,我觉得这也仅仅是个开始,因为就算官方的Wdiget再多也是有限的再多也不一定就能满足你应用的效果。

你以为就我能想到这个?官方肯定也会想到这一点啊,在Flutter中也是支持你自定义viewget的

在Flutter中与绘制相关的是在Painting层次,具体见下图:

Flutter架构图

和Flutter自带的Wdiget一样,自定义的Widget也会经过Skia被编译成原生代码,所以性能上也是不受影响的。

简单的步骤

  1. 新建类继承于CustomPainter实现paint()和shouldRepaint()方法
  2. 在paint方法中绘制你想要的内容
  3. 借助于 CustomPaint Widget来构建自己的Widget

当然,上面仅仅是自定义的流程,具体的实现还是有很多细节需要处理的。

与绘制相关的知识

学过前端或者终端开发的童鞋,应该对绘制都比较熟悉,绘制主要还是靠画布canvas和画笔Paint和完成的,画布就是你绘制图形的地方,画笔就是你用来作画的笔。

画布canvas

画布是一个矩形区域,我们可以控制其每一像素来绘制我们想要的内容

canvas 拥有多种绘制点、线、路径、矩形、圆形、以及添加图像的方法,结合这些方法我们可以绘制出千变万化的画面。

虽然,画布可以画这些东西,但是决定这些图形颜色、粗细表现的还是画笔。

画笔Paint

Paint非常好理解,就是我们用来画图形的工具,我们可以设置画笔的颜色、粗细、是否抗锯齿、笔触形状以及作画风格。

通过这些属性我们可以很方便的来定制自己的UI效果,当然我们在“作画”的过程中可以定义多个画笔,这样更方便我们对图形的绘制

Offset坐标

这个就比较简单,一般指得是在坐标系中的一个点。

Rect

在图形的绘制中,一般都是分区域绘制的,这个区域一般都是一个矩形,在绘制中通常使用Rect来存储绘制的位置信息。

当然,你可以指定Rect的上、下、左、右

  • left : 矩形左边的X坐标
  • top: 矩形顶部的Y坐标
  • right : 矩形右边的X坐标
  • bottom: 矩形底部的Y坐标

使用你这四个值就可以确定这个矩形的位置和大小。

当然,在一些平台还会有Rect.fromCircle(Offset center, double radius)这个方法来构建矩形,其实想起来也是很简单的,center就是圆心的坐标,radius就是圆的半径,由这两个属性构成圆的外切矩形就是我们需要的矩形。

Flutter中的坐标系

在Flutter中坐标系的坐标原点在左上角,X坐标越往右越大,Y坐标越往下越大

因为在View自定义过程中我们需要排放多个View,所哟弄清楚这一点,在以后自定义Wdiget中会轻松很多。

今天,就先说这么多,从下篇文章起我们就回来学习Flutter自定义Widget的相关内容。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章