【问题标题】:Change color on tap in a Flutter application在 Flutter 应用程序中点击更改颜色
【发布时间】:2020-10-07 03:16:17
【问题描述】:

我正在尝试更改由 ListView.Builder 创建的点击卡片的颜色。我尝试使用 Inkwell 并将 listview 包装在容器内。

现在的问题是,如果我单击或点击任何列表项,所有卡片的颜色都会改变。我需要更改我没有点击的卡片的颜色。

简单来说,如果用户点击项目,我想显示它被选中,就像我们在其他应用中看到的那样。

下面是代码。

 @override
  Widget build(BuildContext context) {
     return Theme(
      isMaterialAppTheme: true,
      data: ThemeData(
      ),

     child:Scaffold(
       key: _scaffoldKey,
      appBar: myAppBar(),
      endDrawer: myDrawer(),
        body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,


          children: <Widget>[
            Container(
                decoration: BoxDecoration(
                      color:Colors.grey,
                      borderRadius: BorderRadius.only(
                                  bottomLeft: Radius.circular(4.0),
                                  bottomRight: Radius.circular(4.0))),
              padding: EdgeInsets.symmetric(horizontal:16.0, vertical: 15.0),
              width: double.infinity,
              child: Text("Booking Details",
                textAlign: TextAlign.center,
                style: TextStyle(
                fontSize: 18.0,
                color: Colors.white,
                letterSpacing: 3,
                wordSpacing: 3
              ),)),


            Expanded(child: ListView.builder(
              padding: EdgeInsets.all(16.0),
              itemCount: lists.length,
              itemBuilder: (BuildContext context, int index){
                return Stack(
                  children: <Widget>[
                    Container(
                      decoration: BoxDecoration(
                      color:Colors.grey,
                     ),
                      width: double.infinity,
                      margin: EdgeInsets.only(left:15, right: 15.0, bottom: 10.0),
                      child: Material(
                        borderRadius: BorderRadius.circular(5.0),
                        elevation: 3.0,
                        child:InkWell(
                          onTap: () {
                            setState(() {
                                _color = !_color;
                            });
                          },
                         child: Container(
                               decoration: BoxDecoration(
                                 color: _color ? Colors.deepOrangeAccent : Colors.purpleAccent,
                              ),
                          padding: EdgeInsets.all(16.0),
                          child: Row(
                            children: <Widget>[
                               
                               Expanded(
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                     Text('Class From -: ' + lists[index].title+ ',
                                     style: TextStyle(
                                      fontSize: 14.0,
                                    ),),
                                    SizedBox(height: 10.0,),
                                    Text('Subject -: ' + lists[index].product,
                                     style: TextStyle(
                                      fontSize: 14.0,
                                      
                                    ),),
                                    SizedBox(height: 10.0,),
                                    Text('Price -: ' + lists[index].price.toString() + ' USD  ' + lists[index].serviceType,
                                     style: TextStyle(
                                      fontSize: 16.0,
                                      fontWeight: FontWeight.bold
                                    ),),
                                    SizedBox(height: 20.0,),
                                   
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                        ),
                      ),
                    ),
                     ],
                );
              },

            ),),
            Container(
              decoration: BoxDecoration(
              color:Colors.black12,
              ),
              width: double.infinity,
              padding: EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: <Widget>[
                  Text("Subtotal      \$50", style: TextStyle(
                    color: Colors.grey.shade700,
                    fontSize: 16.0
                  ),),
                  SizedBox(height: 5.0,),
                  Text("Delivery       \$05", style: TextStyle(
                    color: Colors.grey.shade700,
                    fontSize: 16.0
                  ),),
                  SizedBox(height: 10.0,),
                  Text("Cart Subtotal     \$55", style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 18.0
                  ),),
                  SizedBox(height: 20.0,),
                  SizedBox(
                    width: double.infinity,
                    child: MaterialButton(
                      height: 50.0,
                      color: Colors.pinkAccent,
                      child: Text("Secure Checkout".toUpperCase(), style: TextStyle(
                        color: Colors.white
                      ),),
                      onPressed: (){},
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),

我在这里做错了什么?

【问题讨论】:

  • //这里定义索引 int _selectedIndex = -1; //然后更新索引 setState(() { _selectedIndex = index; }); //并更新颜色逻辑颜色:index ==_selectedIndex ? Colors.deepOrangeAccent : Colors.purpleAccent,
  • @Gaurav 感谢您的评论。你能给我举个例子吗?

标签: flutter


【解决方案1】:

第 1 步:使用默认值 -1 定义索引

int _selectedIndex = -1;

第 2 步:点击列表项时更新索引

InkWell(
    onTap: () {
      setState(() {
        if(_selectedIndex == index){
          _selectedIndex= -1;
         }else{
         _selectedIndex= index;
        }
      });
    },

第 3 步:更新您的项目颜色逻辑

 decoration: BoxDecoration(color: index== _selectedIndex  ? 
                                  Colors.deepOrangeAccent : 
                                  Colors.purpleAccent,),

【讨论】:

  • 我想要的只是一件事。如果我再次点击,那么我该如何更改颜色。目前选定的项目没有被取消选择。
【解决方案2】:

您可以在对象类中创建一个 bool 字段而不是 _color 变量,在我的例子中,我创建了一个带有以下字段的 Booking 类进行测试:

class Booking {
    String title;
    String subject;
    int price;
    bool selected;
    Booking({this.title, this.subject, this.price, this.selected});
}
// list example
List<Booking> lists = [
    Booking(title: "Title", subject: "Subject", price: 10, selected: false),
    Booking(title: "Title", subject: "Subject", price: 10, selected: false),
    Booking(title: "Title", subject: "Subject", price: 10, selected: false),
    Booking(title: "Title", subject: "Subject", price: 10, selected: false),
    Booking(title: "Title", subject: "Subject", price: 10, selected: false)
];

在您的 Inkwell ontap 中,像这样控制选定的变量:

onTap: () {
    setState(() {
         lists[index].selected = !lists[index].selected;
    });

},

在您的 Inkwell boxdecoration 中,将其更改为此,以便检查是否选择了单个对象:

child: Container(
    decoration: BoxDecoration(
    color: lists[index].selected ? Colors.deepOrangeAccent : Colors.purpleAccent,
),

它适用于 dartpad。 Screenshot

【讨论】:

  • 你好 Nickypangers,你这里的代码看起来很棒,你能把整个代码粘贴到这里吗?
  • @Jan HI 我没有原始代码,但我刚刚根据我写的答案制作了一个新代码:dartpad.dev/0017f137e73a196c6b2ee400d2e31642?
【解决方案3】:

一旦我尝试过这种方法。试试看吧。

定义一个全局布尔数组“isSelect”。每个卡片项目的布尔值。

List<bool> isSelect = [false, false, false, false, false, false];

在 Inkwell 小部件 ontap() 时切换布尔值。 根据布尔值isSelect设置if条件下卡片的颜色。

    return InkWell(
    onTap: () {
      setState(() {
        isSelect.setAll(0, [false, false, false, false, false, false]);
        isSelect[ItemID] = !isSelect[ItemID];
      });
      //print("selected " + selectedName);
    },
    child: Container(
        decoration: BoxDecoration(
            color: isSelect[ItemID] ? Colors.orange : Colors.grey,
            borderRadius: BorderRadius.circular(50.0)
        ),
        width: 150,
        height: 150,
        child: Column(
          ...

        )));

【讨论】:

  • 感谢乔治的回答。我的卡片是从数据库生成的。数字可能会有所不同。我不明白你为什么要定义这个。 isSelect.setAll(0, [false, false, false, false, false, false]);
  • 在我的情况下,一次只选择一个项目。我用它来更改其他项目以取消选择。
【解决方案4】:

试试这个例子

class Sample extends StatefulWidget {
  @override
  _SampleState createState() => _SampleState();
}

class _SampleState extends State<Sample> {
  bool isPressed = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          Column(
            children: [
              InkWell(
                onTap: () {
                  setState(() {
                    isPressed = !isPressed;
                  });
                },
                child: Container(
                  height: 50,
                  width: 50,
                  color: isPressed ? Colors.green : Colors.blue,
                ),
              ),
              SizedBox(height: 10),
              InkWell(
                onTap: () {
                  setState(() {
                    isPressed = !isPressed;
                  });
                },
                child: Container(
                  height: 50,
                  width: 50,
                  color: isPressed ? Colors.green : Colors.blue,
                ),
              ),
              SizedBox(height: 10),
              ChangeColor(
                isPressed: isPressed,
              ),
              SizedBox(height: 10),
              ChangeColor(),
            ],
          )
        ],
      ),
    );
  }
}

class ChangeColor extends StatefulWidget {
  const ChangeColor({
    Key key,
    this.isPressed = false,
  }) : super(key: key);
  final bool isPressed;

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

class _ChangeColorState extends State<ChangeColor> {
  bool _isPressed;
  @override
  void initState() {
    super.initState();
    _isPressed = widget.isPressed;
  }

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        setState(() {
          _isPressed = !_isPressed;
        });
      },
      child: Container(
        height: 50,
        width: 50,
        color: _isPressed ? Colors.green : Colors.blue,
      ),
    );
  }
}

【讨论】:

  • 感谢您的回答。我会检查并确认。
【解决方案5】:
  • 将 Card 小部件包装在 StatefulWidget 小部件上。
  • 将 Card 小部件作为孩子传递给您。
  • 添加“颜色”属性并复制其他属性。
  • 从 build method() 返回新的 Card 小部件。

像这样:

SelectableCard(
  card: Card(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(8.0)),
    child: const Text('UI/UX')),
)
class SelectableCard extends StatefulWidget {
  final Card card;

  const SelectableCard({Key? key, required this.card}) : super(key: key);

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

class _SelectableCardState extends State<SelectableCard> {
  bool isSelect = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          isSelect = !isSelect;
        });
      },
      child: Card(
        color: isSelect ? Colors.grey : widget.card.color,
        shape: widget.card.shape,
        child: widget.card.child,
      ),
    );
  }
}

【讨论】:

    猜你喜欢
    • 2019-05-06
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多