1

我正在尝试在卡片小部件中实现通话按钮,

当我按下通话按钮时,我希望整个卡片背景变为蓝色(如选中),并在按下任何其他卡片时恢复正常,比如让通话按钮切换卡片选择,尝试使用setState 函数,但它不起作用,因为它仅在我点击整张卡片而不是其中的特定按钮时才会改变颜色。如何在按下通话按钮时选择整张卡并在按下任何其他卡时释放(从拨号器应用程序返回后)

这是我的代码:

_launchCaller() async {
  const url = "tel:+972545522973";
  if (await canLaunch(url)) {
    await launch(url);
  } else {
    throw 'Could not launch $url';
  }
}
return Padding(
  padding: const EdgeInsets.only(top: 8.0),
  child: Card(
    margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
    color: Colors.brown[30],
    child: ListTile(
      isThreeLine: true,
      title: Row(
        children: <Widget> [
          Container(
            child:Text(widget.helpRequest.category.description) ,
            alignment: Alignment.topLeft,
          ),
          Spacer(),
          Container(
            child:Text(formatter.format(now)),
            alignment: Alignment.topRight,
          ),
        ]
      )
      ,
      subtitle: Container(
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            GetUserName(widget.helpRequest.sender_id, DataBaseService().userInNeedCollection),
            Text(widget.helpRequest.description),
          ]
        )
      ),
      trailing: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          GestureDetector(
            onTap: (){
              _launchCaller();
              ** Here i think I should add the code **
            },
            onLongPress: () => print("Long Press: Call"),
            child: Padding(
                padding: EdgeInsets.all(16.0),
                child: Icon(Icons.call,
                    size: 20.0,
                    color: Colors.green,
                    )
            ),
          ),
        ],
      ),
    ),
  ),
);

我尝试使用的这个 setState 函数在我的情况下效果不佳(我正在更改 onTap 函数的状态):

void initState() {
           super.initState();

            color = Colors.transparent;
  }
4

2 回答 2

2

最终输出:

在此处输入图像描述

您可以设置特定卡片的颜色,但要做到这一点,您需要有一些方法来引用所选卡片已被点击,通过此引用我们可以决定是否选择卡片,如果是则更改颜色根据我们的喜好。

在以下示例中,我或多或少使用了您在问题中所述的相同卡片小部件模板,然后我使用ListView.builder渲染五张卡片,每张卡片具有相同的功能。

每当按下呼叫按钮时,index该特定卡片的对应项就会分配给状态selectedIndex,并且我们可以将颜色分配给选定的卡片。

这是完整的示例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      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> {
  int selectedIndex;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.only(top: 8.0),
        child: ListView.builder(
          itemCount: 5,
          itemBuilder: (context, index) {
            return Padding(
              padding: const EdgeInsets.only(top: 8.0),
              child: Card(
                margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
                color: index == selectedIndex
                    ? Colors.amberAccent
                    : Colors.brown[30],
                child: ListTile(
                  isThreeLine: true,
                  title: Row(children: <Widget>[
                    Container(
                      child: Text("Some Text"),
                      alignment: Alignment.topLeft,
                    ),
                    Spacer(),
                    Container(
                      child: Text("Some Text"),
                      alignment: Alignment.topRight,
                    ),
                  ]),
                  subtitle: Container(
                      child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                        Text("Some Text"),
                      ])),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      GestureDetector(
                        onTap: () {
                          setState(() {
                            selectedIndex = index;
                          });
                        },
                        onLongPress: () => print("Long Press: Call"),
                        child: Padding(
                          padding: EdgeInsets.all(16.0),
                          child: Icon(
                            Icons.call,
                            size: 20.0,
                            color: Colors.green,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}
于 2020-12-09T09:28:42.443 回答
1

跟踪单击的项目并传递列表的索引

int clickedItemPosition = -1;
  
bool isChecked(currentPosition) => clickedItemPosition == currentPosition;

然后在你的卡里

 //..
Card(
    margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
    color: isChecked(index) ? Colors.blue : Colors.transparent,
//..

在手势检测器中更新clickedItemPosition

//...
GestureDetector(
            onTap: () => setState(() => clickedItemPosition = index),
            //..
于 2020-12-09T09:26:45.700 回答