首页 > 解决方案 > Flutter 浮动操作按钮错误!尝试创建一排具有响应式触摸效果的按钮

问题描述

我的代码:

bool _isClicked = false;

@override
  Widget build(BuildContext context) {
    return Scaffold(
    body: Padding(
      padding: EdgeInsets.symmetric(horizontal: 3.0),
      child: Container(
        decoration: BoxDecoration(
          color: _isClicked ? Colors.orange[300] : Colors.white,
          borderRadius: BorderRadius.circular(30.0),
        ),
        child: FlatButton(
          splashColor: Colors.orange[300],
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(30.0),
          ),
          onPressed: () {
            setState(() {
              _isClicked = !_isClicked;
            });
          },
          child: Padding(
            padding: EdgeInsets.symmetric(
              horizontal: 20.0,
            ),
            child: Text(
              foodItem,
              style: TextStyle(
                fontSize: 20.0,
                color: _isClicked ? Colors.white : Colors.grey[700],
              ),
            ),
          ),
        ),
      ),
     ),
   );

现实:

一个1 二2

期待:

  1. 当我单击一个按钮时,只有那个变成橙色,其余的保持白色。
  2. 当我再次单击它时,它再次变成灰色,就像其他的一样。

标签: flutterflutter-layoutflutter-animationflutter-webflutter-test

解决方案


我相信您想为按钮实现某种切换行为。尽管ToggleBar小部件对此有好处,但它对子小部件的期望并不灵活。因此,ButtonBar小部件对于有关单击的按钮的某种内部状态会很有帮助。这是一个可能对您有所帮助的可行解决方案。相同的代码可在此处作为 codepen 使用。

方法

  1. 将您的按钮代码提取到一个TButton使用参数调用的小部件中,如下所示
    • isClicked- 一个布尔标志,表示是否单击了按钮。
    • foodItem- 要在按钮上显示的文本。
    • onPressed- 按下按钮时要调用的回调函数。
  2. 在父小部件MyButtons中保存一个列表,bool指示每个按钮的单击状态。
  3. MyButtons接受foodItems. 迭代这个列表并生成一个TButton小部件列表并将其传递给ButtonBar作为子级。
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          primarySwatch: Colors.blue, scaffoldBackgroundColor: darkBlue),
      home: Scaffold(
        body: MyButtons(foodItems: ['Pizza', 'Burger', 'Kebab']),
      ),
    );
  }
}

class MyButtons extends StatefulWidget {
  MyButtons({Key key, this.foodItems}) : super(key: key);

  final List<String> foodItems;

  @override
  _MyButtonsState createState() => _MyButtonsState();
}

class _MyButtonsState extends State<MyButtons> {
  List<bool> isSelected;

  @override
  initState() {
    super.initState();
    // initialize the selected buttons
    isSelected = List<bool>.generate(widget.foodItems.length, (index) => false);
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      // just for aesthetics
      padding: const EdgeInsets.only(top: 80.0),
      child: ButtonBar(        
        // use the alignment to positon the buttons in the screen horizontally
        alignment: MainAxisAlignment.center,
        // iterate over the foodItems and generate the buttons.
        children: widget.foodItems.asMap().entries.map((entry) {
          return TButton(
              isClicked: isSelected[entry.key],
              foodItem: entry.value,
              onPressed: () {
                setState(() {
                  isSelected[entry.key] = !isSelected[entry.key];
                });
              });
        }).toList(),
      ),
    );
  }
}

class TButton extends StatelessWidget {
  final bool isClicked;
  final String foodItem;
  /// OnPressed is passed from the parent. This can be changed to handle it using any state management.
  final Function onPressed;

  TButton(
      {@required this.isClicked,
      @required this.foodItem,
      @required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: isClicked ? Colors.orange[300] : Colors.white,
        borderRadius: BorderRadius.circular(30.0),
      ),
      child: FlatButton(
        splashColor: Colors.orange[300],
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(30.0),
        ),
        onPressed: onPressed,
        child: Padding(
          padding: EdgeInsets.symmetric(
            horizontal: 20.0,
          ),
          child: Text(
            foodItem,
            style: TextStyle(
              fontSize: 20.0,
              color: isClicked ? Colors.white : Colors.grey[700],
            ),
          ),
        ),
      ),
    );
  }
}


推荐阅读