【Flutter 专题】122 图解自定义半遮挡头像 SeriesCircleProfile & CircleAvatar

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜在学习过程中,想实现一行半遮挡的用户头像的功能,横向展示过程中,具体包括 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"右侧头像逐个半遮挡左侧头像","attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"左侧头像逐个半遮挡右侧头像","attrs":{}},{"type":"text","text":" 两种展示;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可展示本地图或网络图;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可自定义末尾图标;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可自定义边框样式;","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    整个自定义过程主要是通过基础的 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Stack","attrs":{}},{"type":"text","text":" 层级和 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Positioned","attrs":{}},{"type":"text","text":" 设置偏移量来完成,小菜仅记录一下在测试过程中遇到的小问题;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/13/134336a85fdf5812ab18692dddee1293.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"SeriesCircleProfile","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 左右半遮挡","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜预想的核心功能,是实现不同方向的叠加遮挡效果;其中合适准备采用 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Stack","attrs":{}},{"type":"text","text":" 小组件作为头像的层级展示,在通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Positioned","attrs":{}},{"type":"text","text":" 设置偏移量来设置半遮挡效果;其中 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Stack","attrs":{}},{"type":"text","text":" 中的子 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Widget","attrs":{}},{"type":"text","text":" 是以栈的方式存储的,即数组后面的元素会覆盖前面的元素;因此左右半遮挡效果主要通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Positioned","attrs":{}},{"type":"text","text":" 设置偏移量来完成;小菜通过定义 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"isCoverUp","attrs":{}},{"type":"text","text":" 来判断半遮挡顺序;","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.1 右侧半遮挡左侧","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    右侧半遮挡左侧相对较容易,仅需将数组中元素向右侧偏移固定偏移量即可;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"List _listWid = [Container(height: size)];\nfor (int i = 0; i < urlList.length; i++) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n}\nreturn Stack(children: _listWid);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/88/8877b5b0194ec01f8b4cdb55665cb0af.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.2 左侧半遮挡右侧","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    左侧半遮挡右侧,小菜通过数组倒序方式,然后再将数组向右侧设置固定偏移量;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"List _listWid = [Container(height: size)];\nfor (int i = urlList.length - 1; i >= 0; i--) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n}\nreturn Stack(children: _listWid);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a7/a74ed5bb609019d84876fd58bcd3d121.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. 本地图 & 网络图","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜在自定义传递头像 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"URL","attrs":{}},{"type":"text","text":" 时考虑到,可能是网络图也可能是本地图,甚至是两者混合展示的;主要分为两类:","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1 纯本地图 & 纯网络图","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜设置 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"isAsset","attrs":{}},{"type":"text","text":" 为 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"urlList","attrs":{}},{"type":"text","text":" 中公共的图片属性,本地图或网络图;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"if (isCoverUp ?? true) {\n if (urlList != null) {\n for (int i = urlList.length - 1; i >= 0; i--) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n }\n }\n} else {\n if (urlList != null) {\n for (int i = 0; i < urlList.length; i++) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/14/1424cc0f960ad00e6ed8211e542e94c1.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2 本地图片 + 网络图混合","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜设置一个 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"List>","attrs":{}},{"type":"text","text":" 类型的 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"mixUrlList","attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Map","attrs":{}},{"type":"text","text":" 中存储是否为本地图和图片地址,遍历加载时通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"bool","attrs":{}},{"type":"text","text":" 类型判断即可;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"if (isCoverUp ?? true) {\n if (mixUrlList != null) {\n for (int i = mixUrlList.length - 1; i >= 0; i--) {\n _listWid.add(_itemWid(mixUrlList[i].keys.first, mixUrlList[i].values.first, i, null));\n }\n }\n} else {\n if (mixUrlList != null) {\n for (int i = 0; i < mixUrlList.length; i++) {\n _listWid.add(_itemWid(mixUrlList[i].keys.first ?? false, mixUrlList[i].values.first, i, null));\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/2f/2fce03c2dd644279e4fef33ea69c5ffb.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 末尾图标","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    在用户头像较多点情况下,很多场景需要一个末尾省略图标,小菜提供了一个 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"endIcon","attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Widget","attrs":{}},{"type":"text","text":" 以供自定义图标的样式,可以是图片或文字或其他等展示效果;值得注意的是,之前小菜设置了 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"右侧半遮挡左侧","attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"左侧半遮挡右侧","attrs":{}},{"type":"text","text":" 两种效果;因此该图标不仅需要对应的偏移量,还需要针对这两种情况先后不同顺序添加在 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Stack","attrs":{}},{"type":"text","text":" 栈内;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"List _listWid = [Container(height: size)];\nif (isCoverUp ?? true) {\n if (urlList != null) {\n if (endIcon != null) {\n _listWid.add(_itemWid(isAsset ?? false, null, urlList.length, endIcon));\n }\n for (int i = urlList.length - 1; i >= 0; i--) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n }\n } else if (mixUrlList != null) {\n if (endIcon != null) {\n _listWid.add(_itemWid(isAsset ?? false, null, mixUrlList.length, endIcon));\n }\n for (int i = mixUrlList.length - 1; i >= 0; i--) {\n _listWid.add(_itemWid(mixUrlList[i].keys.first, mixUrlList[i].values.first, i, null));\n }\n }\n} else {\n if (urlList != null) {\n for (int i = 0; i < urlList.length; i++) {\n _listWid.add(_itemWid(isAsset ?? false, urlList[i], i, null));\n }\n if (endIcon != null) {\n _listWid.add(_itemWid(isAsset ?? false, null, urlList.length, endIcon));\n }\n } else if (mixUrlList != null) {\n for (int i = 0; i < mixUrlList.length; i++) {\n _listWid.add(_itemWid(mixUrlList[i].keys.first ?? false, mixUrlList[i].values.first, i, null));\n }\n if (endIcon != null) {\n _listWid.add(_itemWid(isAsset ?? false, null, mixUrlList.length, endIcon));\n }\n }\n}\n\nreturn Stack(children: _listWid);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/85/8510aba415e35212b15305a0f98a98a3.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4. 自定义 Border","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    对于个性化需求,是否需要边框,以及边框颜色和粗细,这些属于相对简单边缘的功能点;小菜予以补充,添加了 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"isBorder、borderColor 和 borderWidth","attrs":{}},{"type":"text","text":" 属性;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"return Positioned(\n left: (spaceWidth ?? _kSpaceWidth) * index,\n child: Container(\n width: size, height: size,\n decoration: BoxDecoration(\n border: (isBorder ?? false) == false ? null : Border.all(color: borderColor ?? _kBorderColor, width: borderWidth ?? _kBorderWidth),\n color: Colors.grey, shape: BoxShape.circle),\n child: PhysicalModel(\n color: Colors.transparent, shape: BoxShape.circle,\n clipBehavior: Clip.antiAlias, borderRadius: BorderRadius.all(Radius.circular(20.0)),\n child: Container(width: size, height: size,\n child: endIcon ?? (asset ? Image.asset(url) : Image.network(url))))));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fe/fe88a7e76e0cf8b92d3d202ae8aa2adc.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"CircleAvatar","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜在设置圆形头像时了解到 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":" 组件,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Flutter","attrs":{}},{"type":"text","text":" 提供了很多绘制圆形的方法,小菜趁此机会简单学习一下 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":";","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":" 比较特殊,通常用于用户图片和内容一同展示,且为了保持效果一致,给定用户的姓名缩写应始终与相同的背景色配对;","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"源码分析","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const CircleAvatar({\n Key key,\n this.child, // 子 Widget\n this.backgroundColor, // 背景色\n this.backgroundImage, // 背景图\n this.foregroundColor, // 子 Widget 颜色\n this.radius, // 半径\n this.minRadius, // 最小半径\n this.maxRadius, // 最大半径\n})\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    简单分析源码可得,主要是通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"BoxConstraints","attrs":{}},{"type":"text","text":" 来限制最大最小半径,而 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"backgroundImage","attrs":{}},{"type":"text","text":" 来设置背景图;","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"案例尝试","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1. child","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"child","attrs":{}},{"type":"text","text":" 为 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":" 中居中展示的子 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Widget","attrs":{}},{"type":"text","text":",一般是 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"TextView","attrs":{}},{"type":"text","text":",用于展示姓名等;若设置图片则不会进行圆形裁切;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"return CircleAvatar(radius: 40.0, child: Text(index == 0 ? 'ACE' : 'Hi'));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cd/cd01a2e81e0a5fc449b21833bac5f2a4.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. backgroundImage","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"backgroundImage","attrs":{}},{"type":"text","text":" 为 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":" 图片背景,默认居中裁切,注意 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"backgroundImage","attrs":{}},{"type":"text","text":" 对应的是 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"ImageProvider","attrs":{}},{"type":"text","text":" 而非 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Widget","attrs":{}},{"type":"text","text":",因此加载图片时只能采用 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"AssetImage","attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"NetworkImage","attrs":{}},{"type":"text","text":" 方式;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"return CircleAvatar(\n radius: 40.0,\n backgroundImage: index != 0\n ? NetworkImage('https://locadeserta.com/game/assets/images/background/landing/1.jpg')\n : AssetImage('images/icon_hzw01.jpg'));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c0/c0b543b80ac566db7fe85b223885917d.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3. backgroundColor & foregroundColor","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"backgroundColor","attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"foregroundColor","attrs":{}},{"type":"text","text":" 分别对应背景颜色和子 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"child","attrs":{}},{"type":"text","text":" 颜色,除非两个颜色均设置,否则两个背景色会之间会自动匹配;默认 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"backgroundColor","attrs":{}},{"type":"text","text":" 对应 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Theme","attrs":{}},{"type":"text","text":" 的主题颜色;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"return CircleAvatar(\n radius: 40.0,\n child: Text(index == 0 ? 'ACE' : 'Hi'),\n backgroundColor: (index == 0) ? null : Colors.deepOrange,\n foregroundColor: (index == 0) ? null : Colors.blue);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6f/6f7c7bcae2732f2a5411f0b038db568c.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4. radius & minRadius & maxRadius","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    了解源码可得,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CircleAvatar","attrs":{}},{"type":"text","text":" 是通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"BoxConstraints","attrs":{}},{"type":"text","text":" 来限制半径范围的;若设置 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"radius","attrs":{}},{"type":"text","text":" 则其余两个不生效;默认 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"minRadius","attrs":{}},{"type":"text","text":" 为 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"20","attrs":{}},{"type":"text","text":" 像素密度;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"return CircleAvatar(\n maxRadius: 50.0,\n child: Text('ACE'),\n backgroundColor: Colors.deepOrange,\n foregroundColor: Colors.white,\n backgroundImage: AssetImage('images/icon_hzw01.jpg'));\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9b/9bd9f7780985d7903523f4deb4517951.webp","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    ","attrs":{}},{"type":"link","attrs":{"href":"https://github.com/ACE-YANGCE/FlutterApp/blob/master/lib/page/series_circle_page.dart","title":"","type":null},"content":[{"type":"text","text":"SeriesCircleProfile & CircleAvatar 案例源码","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    小菜对于系列折叠头像的自定义较为简单,没有使用复杂的 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Canvas","attrs":{}},{"type":"text","text":" 绘制,而是通过 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Stack","attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Positioned","attrs":{}},{"type":"text","text":" 进行展示,逻辑更为简单;如有错误,请多多指导!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"来源: 阿策小和尚","attrs":{}}]}],"attrs":{}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章