android - Flutter-可以将边界半径提供给扩展面板列表吗?如果是,应该使用哪些属性
问题描述
我有这个扩展面板列表的代码,它工作正常,但我无法扩展扩展面板的大小。另外,我希望扩展面板有一个边框半径,但我不确定是否可以给定边框半径
return Column(children: [
Stack(
clipBehavior: Clip.none,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: ExpansionPanelList(
animationDuration: Duration(milliseconds: 1000),
children: [
ExpansionPanel(
headerBuilder: (context, isExpanded) {
return Column(
children: [
Text("Salmon Poké"),
Text("Rs. 2000"),
],
);
},
body: Text(
'This salmon sashimi is a delicious light appetizer served with fresh wasabi, ginger, soy sauce or a delicious side of soy yuzo citrus ponzu.',
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
isExpanded: _expanded,
canTapOnHeader: true,
backgroundColor: Colors.white),
],
dividerColor: Colors.grey,
expansionCallback: (panelIndex, isExpanded) {
_expanded = !_expanded;
setState(() {});
},
),
),
Positioned(
top: -55,
right: 240,
child: CircleAvatar(
radius: 105,
child: ClipOval(
child: Image(
image: AssetImage('assets/images/salmon.png'),
),
),
backgroundColor: Colors.transparent,
),
),
],
),
]);
} }
**这是给定代码的 UI **
这是我想要的输出。(此 UI 是使用容器小部件制作的,但我希望使用扩展面板列表进行此布局)
我真的很感谢你的帮助。
解决方案
import 'package:flutter/material.dart';
const double _kPanelHeaderCollapsedHeight = 48.0;
const double _kPanelHeaderExpandedHeight = 64.0;
class CustomExpansionPanelList extends StatelessWidget {
const CustomExpansionPanelList(
{Key key,
this.children: const <ExpansionPanel>[],
this.expansionCallback,
this.animationDuration: kThemeAnimationDuration})
: assert(children != null),
assert(animationDuration != null),
super(key: key);
final List<ExpansionPanel> children;
final ExpansionPanelCallback expansionCallback;
final Duration animationDuration;
bool _isChildExpanded(int index) {
return children[index].isExpanded;
}
@override
Widget build(BuildContext context) {
final List<Widget> items = <Widget>[];
const EdgeInsets kExpandedEdgeInsets = const EdgeInsets.symmetric(
vertical: _kPanelHeaderExpandedHeight - _kPanelHeaderCollapsedHeight);
for (int index = 0; index < children.length; index += 1) {
if (_isChildExpanded(index) && index != 0 && !_isChildExpanded(index - 1))
items.add(new Divider(
key: new _SaltedKey<BuildContext, int>(context, index * 2 - 1),
height: 15.0,
color: Colors.transparent,
));
final Row header = new Row(
children: <Widget>[
new Expanded(
child: new AnimatedContainer(
duration: animationDuration,
curve: Curves.fastOutSlowIn,
margin: _isChildExpanded(index)
? kExpandedEdgeInsets
: EdgeInsets.zero,
child: new SizedBox(
height: _kPanelHeaderCollapsedHeight,
child: children[index].headerBuilder(
context,
children[index].isExpanded,
),
),
),
),
new Container(
margin: const EdgeInsetsDirectional.only(end: 8.0),
child: new ExpandIcon(
isExpanded: _isChildExpanded(index),
padding: const EdgeInsets.all(16.0),
onPressed: (bool isExpanded) {
if (expansionCallback != null)
expansionCallback(index, isExpanded);
},
),
),
],
);
double _radiusValue = _isChildExpanded(index)? 8.0 : 0.0;
items.add(
new Container(
key: new _SaltedKey<BuildContext, int>(context, index * 2),
child: new Material(
elevation: 2.0,
borderRadius: new BorderRadius.all(new Radius.circular(_radiusValue)),
child: new Column(
children: <Widget>[
header,
new AnimatedCrossFade(
firstChild: new Container(height: 0.0),
secondChild: children[index].body,
firstCurve:
const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
secondCurve:
const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
sizeCurve: Curves.fastOutSlowIn,
crossFadeState: _isChildExpanded(index)
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: animationDuration,
),
],
),
),
),
);
if (_isChildExpanded(index) && index != children.length - 1)
items.add(new Divider(
key: new _SaltedKey<BuildContext, int>(context, index * 2 + 1),
height: 15.0,
));
}
return new Column(
children: items,
);
}
}
class _SaltedKey<S, V> extends LocalKey {
const _SaltedKey(this.salt, this.value);
final S salt;
final V value;
@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType) return false;
final _SaltedKey<S, V> typedOther = other;
return salt == typedOther.salt && value == typedOther.value;
}
@override
int get hashCode => hashValues(runtimeType, salt, value);
@override
String toString() {
final String saltString = S == String ? '<\'$salt\'>' : '<$salt>';
final String valueString = V == String ? '<\'$value\'>' : '<$value>';
return '[$saltString $valueString]';
}
}
现在在您的应用程序中使用此小部件
import 'package:color_essence/customViews/CustomExpansionList.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class ExpansionPanelDemo extends StatefulWidget {
@override
_ExpansionPanelDemoState createState() => _ExpansionPanelDemoState();
}
class _ExpansionPanelDemoState extends State<ExpansionPanelDemo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expansion Panel Demo'),
),
body: Container(
padding: EdgeInsets.all(10),
child: ListView.builder(
itemCount: itemData.length,
itemBuilder: (BuildContext context, int index) {
return CustomExpansionPanelList(
animationDuration: Duration(milliseconds: 1000),
children: [
ExpansionPanel(
body: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipOval(
child: CircleAvatar(
child: Image.asset(
itemData[index].img,
fit: BoxFit.cover,
),
),
),
SizedBox(
height: 30,
),
Text(
itemData[index].discription,
style: TextStyle(
color: Colors.grey[700],
fontSize: 15,
letterSpacing: 0.3,
height: 1.3),
),
],
),
),
headerBuilder: (BuildContext context, bool isExpanded) {
return Container(
padding: EdgeInsets.all(10),
child: Text(
itemData[index].headerItem,
style: TextStyle(
color: itemData[index].colorsItem,
fontSize: 18,
),
),
);
},
isExpanded: itemData[index].expanded,
)
],
expansionCallback: (int item, bool status) {
setState(() {
itemData[index].expanded = !itemData[index].expanded;
});
},
);
},
),
),
);
}
List<ItemModel> itemData = <ItemModel>[
ItemModel(
headerItem: 'Android',
discription:
"Android is a mobile operating system based on a modified version of the Linux kernel and other open source software, designed primarily for touchscreen mobile devices such as smartphones and tablets. ... Some well known derivatives include Android TV for televisions and Wear OS for wearables, both developed by Google.",
colorsItem: Colors.green,
img: 'assets/images/android_img.png'
),
];
}
class ItemModel {
bool expanded;
String headerItem;
String discription;
Color colorsItem;
String img;
ItemModel({this.expanded: false, this.headerItem, this.discription,this.colorsItem,this.img});
}
推荐阅读
- javascript - 用户输入未正确影响边框半径
- python - 选择总和为一个值同时最小化另一个值的最佳列
- javascript - Javascript异步函数返回承诺而不是实际值
- sql - For循环在R中迭代SQL查询
- api - 是否有完整的 Solr REST API 列表/文档?
- adb - 如何在android adb中访问当前和焦点窗口
- python-3.x - python不会解决我的方程式我该如何解决?
- mongodb - MongoDB 是否有数据存储限制
- sql - Oracle SQL 或 PLSQL 随负载扩展
- pyautogui - PyAutoGUI 错误尝试使用 pyautogui.press()