【问题标题】:Flutter - How to Show/Hide Widget on another ClassFlutter - 如何在另一个类上显示/隐藏小部件
【发布时间】:2019-11-19 14:12:30
【问题描述】:

我有两节课,第一节是Main Widget Screen,第二节是List Card。在 View Perspective 中,Main Widget Screen Class 包含 List Widget from List Card Widget Class ,如下图所示:

List Card 小部件上,每个列表都有 2 个文本:Text1Text2

另外,还有 2 个按钮:this monthlast monthList Card Widget 上的数据将根据 Bloc Stream ZikirHistoryBloc.onChangeTab() 刷新。默认为this month

我想要实现的是:

如何通过Main Screen 上的按钮显示/隐藏(开/关)Text1Text2

到目前为止我的努力:

主屏幕类:

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() {
    return new _MainScreenState();
  }
}

class _MainScreenState extends State<MainScreen> {

  ZikirHistoryBloc zikirHistoryBloc;
  int selectedValue = 1;

...


@override
  Widget build(BuildContext context) {
    return Scaffold(

      ...

       Expanded(
          child: ButtonMenuWidget(
            image: "assets/images/zikir/button-text1.png",
            title: translations.text("button_show_hide_text1"),
            subtitle: point,
            onTap: () {

              //This is action for Button for Show/Hide Text1**

            }
          )
        ),
      Expanded(
        child: ButtonMenuWidget(
          image: "assets/images/home/button-text2.png",
          title: translations.text("button_show_hide_text2"),
          subtitle: dzikir,
          onTap: () {

           //This is action for Button for Show/Hide Text1**

          }
        )
      ),

      ...

      SizedBox(
              width: 1000,
              child: Padding(
                padding: EdgeInsets.all(8),
                child: StreamBuilder(
                  stream: zikirHistoryBloc.tabSelectedValueStream,
                  builder: (context, snapshot) {
                    return CupertinoSegmentedControl<int>(
                      selectedColor: Pigment.fromString(UIData.primaryColor),
                      borderColor: Pigment.fromString(UIData.primaryColor),
                      children:  <int, Widget>{
                        0: Text(translations.text("last_month").toString()),
                        1: Text(translations.text("this_month").toString()),
                      },
                      onValueChanged: (int newValue) {
                        zikirHistoryBloc.onChangeTab(newValue);
                      },
                      groupValue: snapshot.data,
                    );
                  }
                ),
              )
            ),

      ...

      this.HistoriesWidget(),

      ...

}//::end of Widget build

...

Widget HistoriesWidget() {
    return StreamBuilder(
      stream: zikirHistoryBloc.dzikirHistoriesStream,
      builder: (BuildContext ctx, AsyncSnapshot<List<DzikirHistory>> snapshot) {
        if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
        if (!snapshot.hasData) return Center(child: ActivityIndicatorWidget());
        if (snapshot.data.length <= 0) return Center(child: Text(translations.text("empty_data")));

        return ListView.builder(
          shrinkWrap: true,
          itemCount: snapshot.data.length,
          primary: false,
          physics: const NeverScrollableScrollPhysics(),
          itemBuilder: (ctx, i) {

            //**Below will call class ListCardWidget**

            return ListCardWidget(dzikirHistory: snapshot.data[i]);

          }
        );
      }
    );
  }

...

} //::end of Class `Main Screen`

列出卡片小部件类:

class ListCardWidget extends StatefulWidget {

  DzikirHistory dzikirHistory; 
  ListCardWidget({this.dzikirHistory});

  @override
  _ListCardWidget createState() {
    return new _ListCardWidget(dzikirHistory: dzikirHistory);
  }
}

class _ListCardWidget extends State<ListCardWidget> {

  bool isHiddenText1;
  bool isHiddenText2;
  DzikirHistory dzikirHistory; 

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[              
              Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[

                  isHiddenText1 ? Container() : this.Text1Row(context),
                  isHiddenText2 ? Container() : this.Text2Row(context),

                  SizedBox(height: 10,),
                ],
              )
            ],
          ),
        ),
        Divider(height: 2, color: Pigment.fromString(UIData.primaryColor),),
      ],
    );
  }


Widget Text1Row(context) {
  return Column(
    children: <Widget>[
      SizedBox(height: 10,),
      Row(
        children: <Widget>[
          SizedBox(child: Image.asset("assets/images/home/my-zikir-total.png"),height: 20, width: 20,),
          SizedBox(width: 10,),
          Text('Text 1 ='+getNumberFormat(dzikirHistory.dzikirTotal.toString()),
            style: TextStyle(
                fontSize: 16,
                color: Pigment.fromString(UIData.primaryColor)
            ),
          ),
        ],
      ),
    ],
  );
}

Widget Text2Row(context) {
  return Column(
    children: <Widget>[
      SizedBox(height: 10,),
      Row(
        children: <Widget>[
          SizedBox(child: Image.asset("assets/images/home/my-point.png"),height: 20, width: 20,),
          SizedBox(width: 10,),
          Text('Text 2 ='+getNumberFormat(dzikirHistory.counter.toString()),
            style: TextStyle(
                fontSize: 16,
                color: Pigment.fromString(UIData.primaryColor)
            ),
          ),
        ],
      ),
    ],
  );
}  

getNumberFormat(String str) {
    final f = new NumberFormat("#.###");
    return str.replaceAll(f.symbols.GROUP_SEP, '');
}

...

}//end of class List Card Widget

其他类(模型):

class DzikirHistory {

    static const CATEGORY_POINT = "point";
    static const CATEGORY_DZIKIR = "dzikir";

    int id;
    int counter;
    int dzikirTotal;
    String dzikirDate;
    dynamic status;
    dynamic createdAt;
    dynamic updatedAt;
    List<DzikirDetail> dzikirDetails;


    DzikirHistory({
        this.id,
        this.counter,
        this.dzikirTotal,
        this.dzikirDate,
        this.status,
        this.createdAt,
        this.updatedAt,
        this.dzikirDetails
    });

    factory DzikirHistory.fromJson(Map<String, dynamic> json) => new DzikirHistory(
        id: json["id"],
        counter: json["counter"],
        dzikirTotal: json["dzikir_total"],
        dzikirDate: json["dzikir_date"],
        status: json["status"],
        createdAt: DateTime.parse(json["created_at"]),
        updatedAt: DateTime.parse(json["updated_at"]),


        // dzikirDetails: new List<DzikirDetail>.from(json["dzikir_details"].map((x) => DzikirDetail.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "counter": counter,
        "dzikir_total": dzikirTotal,
        "dzikir_date": dzikirDate,
        "status": status,
        "created_at": createdAt.toIso8601String(),
        "updated_at": updatedAt.toIso8601String(),

        // "dzikir_details": new List<dynamic>.from(dzikirDetails.map((x) => x.toJson())),
    };
}

区号:

class ZikirHistoryBloc extends Object implements BlocBase {
...

  init() async {
    _tabSelectedValueController.sink.add(1);
    _userController.sink.add(User.fromJson(await Storage.getUser()));
  }

  onChangeTab(int segment) {
    _tabSelectedValueController.sink.add(segment);
    if (segment == 1) {
      _dzikirHistoriesController.sink.add(dzikirHistories);
    } else {
      _dzikirHistoriesController.sink.add(dzikirLastHistories);
    }
  }
...
}

有什么想法吗?

提前致谢

更新

使用 @FadhliS 解决方案不起作用,因为当我点击上个月时,数据不会刷新(以前是正常的)。此外,仅当我单击上个月或本月按钮时,显示/隐藏才有效。

【问题讨论】:

    标签: flutter dart widget flutter-layout


    【解决方案1】:

    最好的解决方案是使用继承的 widget/provider/scopedModel 插件,因为您希望在从父级到子级的许多类中全局管理状态。您应该阅读这些内容并将它们合并到您的项目中。

    但你也可以试试这个,这是一个小修复,但不是理想的解决方案

    在您的父状态类中创建两个布尔值并将其传递给您的子列表小部件类。你也可以设置状态

    class MainScreen extends StatefulWidget {
      @override
      _MainScreenState createState() {
        return new _MainScreenState();
      }
    }
    
    class _MainScreenState extends State<MainScreen> {
    
      ZikirHistoryBloc zikirHistoryBloc;
      int selectedValue = 1;
    
      //you don't have to declare false as bool is initialised false by default
      bool showText1 = false;
      bool showText2 = false;
    
    
    @override
      Widget build(BuildContext context) {
        return Scaffold(
    
          ...
    
           Expanded(
              child: ButtonMenuWidget(
                image: "assets/images/zikir/button-text1.png",
                title: translations.text("button_show_hide_text1"),
                subtitle: point,
                onTap: () {
                 setState(){
                   showText1 = !showText1;
                 }
                }
              )
            ),
          Expanded(
            child: ButtonMenuWidget(
              image: "assets/images/home/button-text2.png",
              title: translations.text("button_show_hide_text2"),
              subtitle: dzikir,
              onTap: () {
               setState(){
                   showText2 = !showText2;
                 }
              }
            )
          ),
    
          ...
    
          this.HistoriesWidget(),
    
          ...
    
    }//::end of Widget build
    
    ...
    
    Widget HistoriesWidget() {
        return StreamBuilder(
          stream: zikirHistoryBloc.dzikirHistoriesStream,
          builder: (BuildContext ctx, AsyncSnapshot<List<DzikirHistory>> snapshot) {
            if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
            if (!snapshot.hasData) return Center(child: ActivityIndicatorWidget());
            if (snapshot.data.length <= 0) return Center(child: Text(translations.text("empty_data")));
    
            return ListView.builder(
              shrinkWrap: true,
              itemCount: snapshot.data.length,
              primary: false,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (ctx, i) {
    
                //**Below will call class ListCardWidget**
    
                return ListCardWidget(
                  dzikirHistory: snapshot.data[i], 
                 showText1: showText1,
                 showText2: showText2
                );
    
              }
            );
          }
        );
      }
    
    ...
    
    } //
    

    然后在您的列表卡片小部件类中,将其作为参数传递并使用它

    class ListCardWidget extends StatefulWidget {
    
      DzikirHistory dzikirHistory; 
      bool showText1;
      bool showText2;
    
      ListCardWidget({this.dzikirHistory, this.showText1, this.showText2});
    
      @override
      _ListCardWidget createState() {
        //you dont have to pass the elements to your state class
        return new _ListCardWidget();
      }
    }
    
    class _ListCardWidget extends State<ListCardWidget> {
    
      //remove all these variables
      //you can access all the variables directly from the stateful class
      //widget.yourvariable
      bool isHiddenText1;
      bool isHiddenText2;
      DzikirHistory dzikirHistory; 
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            Container(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[              
                  Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
    
                      widget.showText1 ? Container() : this.Text1Row(context),
                      widget.showText2 ? Container() : this.Text2Row(context),
    
                      SizedBox(height: 10,),
                    ],
                  )
                ],
              ),
            ),
            Divider(height: 2, color: Pigment.fromString(UIData.primaryColor),),
          ],
        );
      }
    
    
    Widget Text1Row(context) {
      return Column(
        children: <Widget>[
          SizedBox(height: 10,),
          Row(
            children: <Widget>[
              SizedBox(child: Image.asset("assets/images/home/my-zikir-total.png"),height: 20, width: 20,),
              SizedBox(width: 10,),
              Text('Text 1 ='+getNumberFormat(widget.dzikirHistory.dzikirTotal.toString()),
                style: TextStyle(
                    fontSize: 16,
                    color: Pigment.fromString(UIData.primaryColor)
                ),
              ),
            ],
          ),
        ],
      );
    }
    
    Widget Text2Row(context) {
      return Column(
        children: <Widget>[
          SizedBox(height: 10,),
          Row(
            children: <Widget>[
              SizedBox(child: Image.asset("assets/images/home/my-point.png"),height: 20, width: 20,),
              SizedBox(width: 10,),
              Text('Text 2 ='+getNumberFormat(widget.dzikirHistory.counter.toString()),
                style: TextStyle(
                    fontSize: 16,
                    color: Pigment.fromString(UIData.primaryColor)
                ),
              ),
            ],
          ),
        ],
      );
    }  
    
    getNumberFormat(String str) {
        final f = new NumberFormat("#.###");
        return str.replaceAll(f.symbols.GROUP_SEP, '');
    }
    
    ...
    
    }//end of class List Card Widget
    

    【讨论】:

    • 嗨@FadhliS,我收到错误Error: No named parameter with the name 'dzikirHistory'. return new _ListCardWidget(dzikirHistory: dzikirHistory);Context: The class '_ListCardWidget' has a constructor that takes no arguments. class _ListCardWidget extends State&lt; ListCardWidget &gt; {
    • 但是如果我将构造函数 _ListCardWidget({this.dzikirHistory, this.showText1, this.showText2 }); 添加到类 _ListCardWidget 中,程序将运行但无法显示/隐藏。
    • 谢谢,我也会更新我的代码。实际上,您不必为状态类创建构造函数,只需调用 widget.dzikirHistory 或 widget.showText1 即可。我将在有状态小部件的代码中更改 createState 返回方法
    • @anunixercoder 如果它有效,请支持我的回答。谢谢!
    • 嗨@FadhliS,我已经更新了我的问题和源代码。实际上,有 2 个按钮(this monthlast month)。默认为this month。使用你的方法,我不知道为什么,当我点击last month时,数据不会刷新(以前是正常的)。此外,仅当我单击 last monththis month 按钮时,显示/隐藏才有效。
    猜你喜欢
    • 1970-01-01
    • 2020-10-17
    • 2021-01-17
    • 2017-11-13
    • 2020-11-07
    • 2012-03-07
    • 2019-02-19
    • 2019-01-30
    相关资源
    最近更新 更多