Flutter 自定义单选按钮

Posted

技术标签:

【中文标题】Flutter 自定义单选按钮【英文标题】:Flutter custom radiobuttons 【发布时间】:2021-04-23 20:30:50 【问题描述】:

谁能指导我如何在颤振中实现这一目标? 谢谢

【问题讨论】:

Flutter 提供了一个叫Stepper() 的小部件,看看this 这不是步进器。我已经编辑了问题。这些有点单选按钮。如果我点击 5 则文本将变为 5 分钟,或者如果我点击 15 则时间将变为 15 分钟。 我认为在这里使用步进器实现是正确的,因为它看起来像步进器。您可以轻松地使其行为“像一个单选按钮”... 这个问题解决了还是你还需要解决方案? 【参考方案1】:

给你兄弟.....干杯!!!

class _MyHomePageState extends State<MyHomePage> 



  double width;
  double height;

  int currentValue = 5;

  Map<int,int> minutesCostMap = 
    5: 20,
    10 : 25,
    15 : 30,
    20 : 35,
  ,


  @override
  Widget build(BuildContext context) 

    height = MediaQuery.of(context).size.height;
    width = MediaQuery.of(context).size.width;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 15),
              child: Text("Chris Watson",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 19),),
            ),
            Padding(
              padding: const EdgeInsets.only(bottom: 25),
              child: Text.rich(
                  TextSpan(children: [
                    TextSpan(text: "This "),
                    TextSpan(text: currentValue.toString() + " minutes ",style: TextStyle(fontWeight: FontWeight.bold)),
                    TextSpan(text: "session will cost you "),
                    TextSpan(text: minutesCostMap[currentValue].toString() + "\$",style: TextStyle(fontWeight: FontWeight.bold)),
                  ])
              ),
            ),
            Stack(
              alignment: Alignment.center,
              children: [
                Container(                                  /// GREY HORIZONTAL LINE
                  height: 10,width: width * 0.6,color: Colors.grey[350],
                ),
                Container(
                  width: width * 0.6 + 50,
                  height: 50,
                  child: Row(                            /// ROW OF 4 CIRCLE WIDGETS PLACED ABOVE THAT LNE
                    mainAxisSize: MainAxisSize.max,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      checkpointButton(5,currentValue == 5),
                      checkpointButton(10,currentValue == 10),
                      checkpointButton(15,currentValue == 15),
                      checkpointButton(20,currentValue == 20),
                    ],
                  ),
                ),
                //Positioned(left: 0,chil),
                //Positioned(left: ,child: Container(decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.blue),width: 40,height: 40,)),
                //Positioned(left: ,child: Container(decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.blue),width: 40,height: 40,)),
                //Positioned(left: ,child: Container(decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.blue),width: 40,height: 40,)),
              ],
            ),
            Padding(
              padding: EdgeInsets.only(top: 25),
              child: Container(
                width: width * 0.75,
                height: 40,
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Expanded(
                      flex: 1,
                      child: Container(
                        decoration: BoxDecoration(border: Border.all(color: Colors.blue,width: 1.5)),
                        child: Center(child: Text("CANCEL",style: TextStyle(color: Colors.blue),),),
                      ),
                    ),
                    Container(width: 10,height: 5,),
                    Expanded(
                      flex: 2,
                      child: Container(color: Colors.blue,child: Center(child: Text("ACCEPT",style: TextStyle(color: Colors.white),),),),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  

  Widget checkpointButton(int value,bool isActive)
    return GestureDetector(               /// THIS WILL DETECT A TAP EVENT ON THIS CIRCLE WIDGET
        onTap: ()
          setState(() 
            currentValue = value;         /// IF THE CURRENT VALUE IS SAME AS THE VALUE OF THE CIRCLE, IT WILL CHANGE ITS APPEARANCE TO SHOW THAT ITS ACTIVE
          );
        ,
        child: Container(            /// CIRCLE PRESENT BEHIND PROVIDING THE BLUE BORDER
            height: 50,width: 50,
            decoration: BoxDecoration(shape: BoxShape.circle,border: Border.all(color: isActive ? Colors.blue : Colors.transparent,width: 1.5)),
            child: Center(
                child: Container(        /// INNER CIRCLE CONTAINING THE VALUE
                  decoration: BoxDecoration(shape: BoxShape.circle,color: isActive ? Colors.blue : Colors.grey[350]),
                  width: 40,height: 40,
                  child: Center(child: Text(value.toString(),style: TextStyle(fontWeight: FontWeight.bold,color: isActive ? Colors.white : Colors.black),)),
                  )
            )
        )
    );
  



结果:

编辑:

我已经更新了上面的代码以满足您的要求。基本上我做了什么,我添加了一个地图(minutesCostMap),其中包含分钟列表及其相应的成本。 然后移动到我们显示成本的地方,你可以看到我使用了地图本身的价值。所以我们正在打印的值将输出与提供的分钟相对应的成本(即存在于 currentValue 变量中)

【讨论】:

这有一个问题。我在不同的时间有不同的价格。当我点击 10 分钟时,它显示 10 美元。我想显示 10 分钟 25 美元、15 分钟 35 美元和 20 分钟 45 美元。 您可以硬编码这些值并使用 if 语句,例如 if(minutes ==10)cost = 25 else if(...)...... 或者您可以创建地图。我正在使用第二种方法编辑我的答案。 您能否接受这个答案,它将帮助其他将解决这个问题的人

以上是关于Flutter 自定义单选按钮的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 自定义单选按钮

颤动:自定义单选按钮

轻按一次选择单选按钮

创建自定义单选按钮

跨多个自定义组件使用单选按钮组功能

如何在 Django 中自定义单选按钮