在 Flutter 中按下切换开关时交换小部件
Posted
技术标签:
【中文标题】在 Flutter 中按下切换开关时交换小部件【英文标题】:Swap Widgets on Toggle switch press in Flutter 【发布时间】:2020-12-26 10:03:47 【问题描述】:我正在尝试为颤动的 ToggleSwitch 实现小部件交换。到目前为止,我已经解决了分别更改小部件和 toggleSwitch 的交换。我需要将它们组合起来,所以当我选择一个切换开关时,它会显示它需要显示的小部件,而当另一个切换开关单击第二个小部件时,它会显示在视图中。 即使我工作时小部件正在交换,ToggleSwitch 也不会改变它的状态。 请帮助我改善这一点。非常感谢。
这是我正在尝试解决的 build() 代码 sn-p。
Widget build(BuildContext context)
final petHeader = Container(
alignment: Alignment.center,
color: Colors.white,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Expanded(
flex: 2,
child: Hero(
tag: 'hero',
child: Padding(
padding: EdgeInsets.all(4.0),
child: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.grey[300],
child: Image(
image: AssetImage(
'assets/images/logo_small.png',
),
),
),
),
),
),
Expanded(
flex: 3,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Dog Name',
style: TextStyle(fontSize: 20.0, color: Colors.black87),
),
Text(
'Age',
style: TextStyle(fontSize: 12.0, color: Colors.black87),
),
],
),
),
),
Expanded(
flex: 5,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 12.0,
),
child: Text(
'Daily Guide',
style: TextStyle(fontSize: 32.0, color: Colors.black87),
textAlign: TextAlign.end,
),
),
),
],
),
);
final macroCharts = Center(
child: Text('macro chart here'),
);
final microCharts = Center(
child: Text('micro chart here'),
);
Widget getMacroChart()
return Center(
child: Text('macro chart here'),
);
Widget getMicroChart()
return Center(
child: Text('micro chart here'),
);
Widget getCustomContainer()
switch (selectedWidget)
case widgetMarker.macro:
return getMacroChart();
case widgetMarker.micro:
return getMicroChart();
return getMacroChart();
final userSaveBtn = Container(
margin: EdgeInsets.only(top: 2.0, bottom: 4.0),
alignment: Alignment.center,
// width: MediaQuery.of(context).size.width,
child: ToggleSwitch(
cornerRadius: 4.0,
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height,
fontSize: 20.0,
initialLabelIndex: 0,
activeBgColor: Color(0xFF03B898),
activeFgColor: Colors.white,
inactiveBgColor: Colors.grey[300],
inactiveFgColor: Colors.black54,
labels: [' Macro\nNutrients', ' Micro\nNutrients'],
onToggle: (index)
print('switched to: $index');
setState(()
_swapNutrients = !_swapNutrients;
);
,
),
);
var swapTile = new Container(
child: _swapNutrients ? macroCharts : microCharts,
);
final body =
Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 3,
child: Container(
width: MediaQuery.of(context).size.width,
color: Colors.transparent,
child: Card(
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text(
'Welcome Alucard',
style: TextStyle(fontSize: 28.0, color: Colors.black87),
),
),
),
),
),
Expanded(
flex: 6,
child: Card(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
flex: 1,
child: userSaveBtn,
Expanded(
flex: 7,
child: Container(
width: MediaQuery.of(context).size.width,
color: Colors.transparent,
child: swapTile,//getCustomContainer(),
),
),
],
),
),
),
),
],
);
final lorem = Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec hendrerit condimentum mauris id tempor. Praesent eu commodo lacus. Praesent eget mi sed libero eleifend tempor. Sed at fringilla ipsum. Duis malesuada feugiat urna vitae convallis. Aliquam eu libero arcu.',
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
);
final mainBody = Container(
margin: EdgeInsets.only(
top: 16.0,
),
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(
top: 12.0,
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.5, 1.0],
colors: [
Color(0xFF03B898),
Color(0xFF01816B),
],
),
),
child: Column(
children: <Widget>[
// SizedBox(height: 32.0),
Expanded(
flex: 1,
child: petHeader,
),
Expanded(
flex: 11,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: body,
),
),
// lorem,
],
),
);
return Scaffold(
body: mainBody, //_isShowingDialog ? bodyWithDialog : bodyWithCharts
);
【问题讨论】:
【参考方案1】:您的意思是切换开关的激活没有改变吗? 如果是这样,我很抱歉我误解了你的问题。
我确认切换开关激活通过点击发生变化。
因为每当执行 build() 时,切换开关的 'initialLabelIndex' 为 0,所以没有激活变化。
这里是一个变化点。
initialLabelIndex: _swapNutrients ? 0 : 1,
import 'package:flutter/material.dart';
import 'package:toggle_switch/toggle_switch.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
bool _swapNutrients = false;
@override
void initState()
super.initState();
Widget build(BuildContext context)
final petHeader = Container(
alignment: Alignment.center,
color: Colors.white,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Expanded(
flex: 2,
child: Hero(
tag: 'hero',
child: Padding(
padding: EdgeInsets.all(4.0),
child: Container(),
),
),
),
Expanded(
flex: 3,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Dog Name',
style: TextStyle(fontSize: 20.0, color: Colors.black87),
),
Text(
'Age',
style: TextStyle(fontSize: 12.0, color: Colors.black87),
),
],
),
),
),
Expanded(
flex: 5,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 12.0,
),
child: Text(
'Daily Guide',
style: TextStyle(fontSize: 32.0, color: Colors.black87),
textAlign: TextAlign.end,
),
),
),
],
),
);
final macroCharts = Center(
child: Text('macro chart here'),
);
final microCharts = Center(
child: Text('micro chart here'),
);
Widget getMacroChart()
return Center(
child: Text('macro chart here'),
);
Widget getMicroChart()
return Center(
child: Text('micro chart here'),
);
final userSaveBtn = Container(
margin: EdgeInsets.only(top: 2.0, bottom: 4.0),
alignment: Alignment.center,
// width: MediaQuery.of(context).size.width,
child: ToggleSwitch(
cornerRadius: 4.0,
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height,
fontSize: 20.0,
initialLabelIndex: _swapNutrients ? 0 : 1,
activeBgColor: Color(0xFF03B898),
activeFgColor: Colors.white,
inactiveBgColor: Colors.grey[300],
inactiveFgColor: Colors.black54,
labels: [' Macro\nNutrients', ' Micro\nNutrients'],
onToggle: (index)
print('switched to: $index');
print('switched to: $_swapNutrients');
setState(()
_swapNutrients = !_swapNutrients;
);
,
),
);
var swapTile = new Container(
child: _swapNutrients ? macroCharts : microCharts,
);
final body = Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 3,
child: Container(
width: MediaQuery.of(context).size.width,
color: Colors.transparent,
child: Card(
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text(
'Welcome Alucard',
style: TextStyle(fontSize: 28.0, color: Colors.black87),
),
),
),
),
),
Expanded(
flex: 6,
child: Card(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
flex: 1,
child: userSaveBtn,
),
Expanded(
flex: 7,
child: Container(
width: MediaQuery.of(context).size.width,
color: Colors.transparent,
child: swapTile, //getCustomContainer(),
),
),
],
),
),
),
),
],
);
final lorem = Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec hendrerit condimentum mauris id tempor. Praesent eu commodo lacus. Praesent eget mi sed libero eleifend tempor. Sed at fringilla ipsum. Duis malesuada feugiat urna vitae convallis. Aliquam eu libero arcu.',
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
);
final mainBody = Container(
margin: EdgeInsets.only(
top: 16.0,
),
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(
top: 12.0,
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.5, 1.0],
colors: [
Color(0xFF03B898),
Color(0xFF01816B),
],
),
),
child: Column(
children: <Widget>[
// SizedBox(height: 32.0),
Expanded(
flex: 1,
child: petHeader,
),
Expanded(
flex: 11,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: body,
),
),
// lorem,
],
),
);
return Scaffold(
body: mainBody, //_isShowingDialog ? bodyWithDialog : bodyWithCharts
);
【讨论】:
即使这改变了小部件的视图,切换不会改变它的状态(简单地说->切换开关不会显示它改变为触摸)。我正在考虑解决这个问题 我想看看你的 build() 代码。因为当 'setState' 被调用时,会执行 build 方法。 我改了答案,请尝试测试一下。 它改变了切换开关下的小部件容器,但切换开关不会改变它的切换(从微到宏,反之亦然)。这就是我坚持的地方。仅供参考,我正在使用一个名为 ToggleSwitch 的包 我附上了我的测试结果截图。这不是你想做的吗?以上是关于在 Flutter 中按下切换开关时交换小部件的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:在 ListView 中按下卡片小部件不起作用