如何通过Flutter中的按钮使内容折叠?
How to make the content collapse by a button in Flutter?
我有这样一个专栏,由标题和通过List.generate
创建的内容组成。如何创建将此列表折叠成标题的动画,实际上是通过单击标题本身?
Column(
children: [
GestureDetector(
onTap: () {},
child: Container(
color: Theme.of(context).sliderTheme.inactiveTrackColor,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Center(
child: Text('${category.name}',
style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 16,
color: Theme.of(context).selectedRowColor)),
),
),
),
),
Column(
children: List.generate(category.items.length, (index) {
return Container(
decoration: BoxDecoration(
border: (index + 1) != category.items.length
? Border(
bottom: BorderSide(
color: Style.inactiveColorDark.withOpacity(1.0),
width: 0.5))
: null),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 12,
height: 12,
decoration: BoxDecoration(
color: Color(int.parse(category.color)),
shape: BoxShape.circle),
),
SizedBox(
width: 12,
),
Text('${category.items[index].description}',
style: Theme.of(context)
.primaryTextTheme
.headline1
.copyWith(fontSize: 16)),
],
),
SwitchButton(
isActive: category.items[index].isAdded,
activeColor:
Theme.of(context).sliderTheme.activeTrackColor,
inactiveColor:
Theme.of(context).sliderTheme.inactiveTrackColor,
activeCircleColor:
Theme.of(context).sliderTheme.activeTickMarkColor,
inactiveCircleColor:
Theme.of(context).sliderTheme.inactiveTickMarkColor,
turnOn: () {
ChosenFeeling removingElement = ChosenFeeling(
id: 000,
isAdded: false,
);
// If chosen list is empty
if (chosenfeelings.isEmpty) {
chosenfeelings.add(ChosenFeeling(
isAdded: true, id: category.items[index].id));
} else {
// If user tap on switchButton 2 times
chosenfeelings.removeWhere((element) {
if (element.id != null &&
element.id == category.items[index].id) {
removingElement = element;
}
return _isNeedToRemoveWhenOn(
currentItem: category.items[index],
listItem: element,
);
});
// If list isn`t empty and chosen item isn`t in list
if (category.items[index].id != removingElement.id) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: true,
));
}
}
},
turnOff: () {
ChosenFeeling removingElement = ChosenFeeling(
id: 000,
isAdded: false,
);
if (chosenfeelings.isEmpty) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: false,
));
} else {
// If user tap on switchButton 2 times
chosenfeelings.removeWhere((element) {
if (element.id != null &&
element.id == category.items[index].id) {
removingElement = element;
}
return _isNeedToRemoveWhenOff(
currentItem: category.items[index],
listItem: element,
);
});
// If list isn`t empty and chosen item isn`t in list
if (category.items[index].id != removingElement.id) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: false,
));
}
}
},
)
],
),
),
);
}),
)
],
);
最简单的方法是为此目的使用可扩展包:
https://pub.dev/packages/expandable
在构建方法之外创建可扩展控制器
final ExpandableController _expandableController = ExpandableController();
然后像这样使用它:
ExpandableNotifier(
controller: _expandableController,
child: Column(
children: [
Expandable(
collapsed: ExpandableButton(
child: titleWidget(),
),
expanded: Column(
children: [
ExpandableButton(
child: titleWidget(),
),
list(),
]
),
),
],
),
);
控制器用完别忘了处理
@override
void dispose() {
_expandableController.dispose();
super.dispose();
}
希望这对您有所帮助。您还可以通过一些研究来创建自己的动画
我有这样一个专栏,由标题和通过List.generate
创建的内容组成。如何创建将此列表折叠成标题的动画,实际上是通过单击标题本身?
Column(
children: [
GestureDetector(
onTap: () {},
child: Container(
color: Theme.of(context).sliderTheme.inactiveTrackColor,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Center(
child: Text('${category.name}',
style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 16,
color: Theme.of(context).selectedRowColor)),
),
),
),
),
Column(
children: List.generate(category.items.length, (index) {
return Container(
decoration: BoxDecoration(
border: (index + 1) != category.items.length
? Border(
bottom: BorderSide(
color: Style.inactiveColorDark.withOpacity(1.0),
width: 0.5))
: null),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 12,
height: 12,
decoration: BoxDecoration(
color: Color(int.parse(category.color)),
shape: BoxShape.circle),
),
SizedBox(
width: 12,
),
Text('${category.items[index].description}',
style: Theme.of(context)
.primaryTextTheme
.headline1
.copyWith(fontSize: 16)),
],
),
SwitchButton(
isActive: category.items[index].isAdded,
activeColor:
Theme.of(context).sliderTheme.activeTrackColor,
inactiveColor:
Theme.of(context).sliderTheme.inactiveTrackColor,
activeCircleColor:
Theme.of(context).sliderTheme.activeTickMarkColor,
inactiveCircleColor:
Theme.of(context).sliderTheme.inactiveTickMarkColor,
turnOn: () {
ChosenFeeling removingElement = ChosenFeeling(
id: 000,
isAdded: false,
);
// If chosen list is empty
if (chosenfeelings.isEmpty) {
chosenfeelings.add(ChosenFeeling(
isAdded: true, id: category.items[index].id));
} else {
// If user tap on switchButton 2 times
chosenfeelings.removeWhere((element) {
if (element.id != null &&
element.id == category.items[index].id) {
removingElement = element;
}
return _isNeedToRemoveWhenOn(
currentItem: category.items[index],
listItem: element,
);
});
// If list isn`t empty and chosen item isn`t in list
if (category.items[index].id != removingElement.id) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: true,
));
}
}
},
turnOff: () {
ChosenFeeling removingElement = ChosenFeeling(
id: 000,
isAdded: false,
);
if (chosenfeelings.isEmpty) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: false,
));
} else {
// If user tap on switchButton 2 times
chosenfeelings.removeWhere((element) {
if (element.id != null &&
element.id == category.items[index].id) {
removingElement = element;
}
return _isNeedToRemoveWhenOff(
currentItem: category.items[index],
listItem: element,
);
});
// If list isn`t empty and chosen item isn`t in list
if (category.items[index].id != removingElement.id) {
chosenfeelings.add(ChosenFeeling(
id: category.items[index].id,
isAdded: false,
));
}
}
},
)
],
),
),
);
}),
)
],
);
最简单的方法是为此目的使用可扩展包: https://pub.dev/packages/expandable
在构建方法之外创建可扩展控制器
final ExpandableController _expandableController = ExpandableController();
然后像这样使用它:
ExpandableNotifier(
controller: _expandableController,
child: Column(
children: [
Expandable(
collapsed: ExpandableButton(
child: titleWidget(),
),
expanded: Column(
children: [
ExpandableButton(
child: titleWidget(),
),
list(),
]
),
),
],
),
);
控制器用完别忘了处理
@override
void dispose() {
_expandableController.dispose();
super.dispose();
}
希望这对您有所帮助。您还可以通过一些研究来创建自己的动画