简体   繁体   中英

Flutter - How to Show/Hide Widget on another Class

I have 2 class, the first one is Main Widget Screen and 2nd is List Card . In View Perspective, Main Widget Screen Class contain List Widget from List Card Widget Class , as seen as below picture :

Flutter UI Widget(显示/隐藏)概念视图

On List Card Widget, every list has 2 Text: Text1 and Text2 .

also, there're 2 button: this month and last month . data on List Card Widget will refresh according to Bloc Stream ZikirHistoryBloc.onChangeTab() . the default is this month .

What i want to achieve is :

How to Show/Hide (On/Off) Text1 and Text2 by button on Main Screen ?

My Effort so far:

Main Screen Class :

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`

List Card Widget Class :

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

Other Class (Model) :

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())),
    };
}

Bloc Code:

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);
    }
  }
...
}

Any Idea ?

Thanks In Advance

UPDATE

Using @FadhliS solution not working because when i click last month the data wont refresh (previously it's normal). also, the show/hide only works if i click last month or this month button.

The best solution would be using inherited widget/provider/scopedModel plugins as you want to manage the state globally across many classes from parent to children.You should read about those and incorporate them into your project.

But you can also try this, it's a small fix but not the ideal solution

Create two booleans in your parent state class and pass it to your child list widget class. You can set state to those too

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
            );

          }
        );
      }
    );
  }

...

} //

And then in your list card widget class, pass it as parameter and use it

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM