แสดง / ซ่อนวิดเจ็ตใน Flutter โดยทางโปรแกรม


135

ใน Android ทุกViewคลาสย่อยจะมีsetVisibility()วิธีการที่ช่วยให้คุณแก้ไขการเปิดเผยของViewวัตถุได้

การตั้งค่าการมองเห็นมี 3 ตัวเลือก:

  • มองเห็นได้: แสดงสิ่งที่Viewมองเห็นได้ภายในเค้าโครง
  • ล่องหน: ซ่อนViewแต่ทิ้งช่องว่างที่เทียบเท่ากับสิ่งที่Viewจะครอบครองหากมองเห็นได้
  • หายไป: ซ่อนViewและลบทั้งหมดออกจากเค้าโครง ราวกับว่าเป็นheightและwidthเป็น0dp

มีสิ่งที่เทียบเท่ากับข้างต้นสำหรับวิดเจ็ตใน Flutter หรือไม่?

สำหรับข้อมูลอ้างอิงอย่างรวดเร็ว: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

คำตอบ:


90

อัปเดต: เนื่องจากคำตอบนี้ถูกเขียนขึ้นจึงVisibilityได้รับการแนะนำและให้วิธีแก้ปัญหาที่ดีที่สุดสำหรับปัญหานี้


คุณสามารถใช้Opacityกับopacity:ของ0.0ที่จะวาดให้องค์ประกอบที่ซ่อนอยู่ แต่ยังคงใช้พื้นที่

Container()ที่จะทำให้มันไม่ใช้พื้นที่แทนที่ด้วยที่ว่างเปล่า

แก้ไข: ในการรวมไว้ในวัตถุทึบให้ทำดังต่อไปนี้:

            new Opacity(opacity: 0.0, child: new Padding(
              padding: const EdgeInsets.only(
                left: 16.0,
              ),
              child: new Icon(pencil, color: CupertinoColors.activeBlue),
            ))

บทแนะนำสั้น ๆ เกี่ยวกับ Opacity ของ Google Developers: https://youtu.be/9hltevOHQBw


3
ขอขอบคุณ! ใช่นั่นไม่ใช่วิธีที่สะอาดที่สุดในการทำ แต่มันจะบรรลุวัตถุประสงค์อย่างแน่นอน มีโอกาสที่จะมีฟังก์ชันการมองเห็นที่ผสานรวมกับวิดเจ็ตในอนาคตหรือไม่?
user3217522

4
หากวิดเจ็ตตอบสนองต่อการป้อนข้อมูลของผู้ใช้ตามปกติให้แน่ใจว่าได้รวมวิดเจ็ตไว้ด้วยไม่IgnorePointerเช่นนั้นผู้ใช้ยังคงสามารถเรียกใช้งานได้
Duncan Jones

1
สิ่งนี้ไม่เหมาะอย่างยิ่งเนื่องจากวิดเจ็ตยังคงอยู่ที่นั่นและสามารถตอบสนองต่อการแตะ ฯลฯ ดูคำตอบด้านล่างโดยใช้วิดเจ็ตการมองเห็นสำหรับวิธีที่ดีที่สุดในการจัดการสิ่งนี้
Russell Zornes

ดังที่ความคิดเห็นกล่าวไว้การใช้ความทึบจะทำให้วิดเจ็ตแสดงผลที่ renderTree โดยในบางกรณีไม่ใช่สิ่งที่คุณต้องการ แนะนำให้ใช้วิดเจ็ตการเปิดเผยมากที่สุด
Isac Moura

การทำให้วิดเจ็ตมองไม่เห็นและมีความทึบเป็น 0 เป็นสองสิ่งที่แตกต่างกัน ด้วยวิดเจ็ตที่มองไม่เห็นคุณยังสามารถโต้ตอบกับมันได้ แต่มันก็มองไม่เห็น วิดเจ็ตการมองเห็นช่วยให้คุณสามารถลบวิดเจ็ตได้จนกว่าจะจำเป็น
UndercoverCoder

203

ล่องหน : วิดเจ็ตใช้พื้นที่ทางกายภาพบนหน้าจอ แต่ผู้ใช้มองไม่เห็น

หายไป : วิดเจ็ตไม่ใช้พื้นที่ทางกายภาพใด ๆ และหายไปอย่างสมบูรณ์


ตัวอย่างที่มองไม่เห็น

Visibility(
  child: Text("Invisible"),
  maintainSize: true, 
  maintainAnimation: true,
  maintainState: true,
  visible: false, 
),

ตัวอย่างไปแล้ว

Visibility(
  child: Text("Gone"),
  visible: false,
),

หรือคุณสามารถใช้ifเงื่อนไขสำหรับทั้งที่มองไม่เห็นและหายไป

Column(
  children: <Widget>[
    if (show) Text("This can be visible/not depending on condition"),
    Text("This is always visible"),
  ],
) 

21
ว่าสภาพ 'ถ้า' สมบูรณ์!
johnc

วิธีใช้เงื่อนไขอื่นที่นี่?
เรียนด่วน

@Quicklearner You can useif(show) Text('Showing) else Text('Not showing)
CopsOnRoad

64

Container()การทำงานร่วมกันกับคำถามและแสดงตัวอย่างของการแทนที่ด้วยที่ว่างเปล่า

นี่คือตัวอย่างด้านล่าง:

ป้อนคำอธิบายภาพที่นี่

import "package:flutter/material.dart";

void main() {
  runApp(new ControlleApp());
}

class ControlleApp extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "My App",
      home: new HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage> {
  bool visibilityTag = false;
  bool visibilityObs = false;

  void _changed(bool visibility, String field) {
    setState(() {
      if (field == "tag"){
        visibilityTag = visibility;
      }
      if (field == "obs"){
        visibilityObs = visibility;
      }
    });
  }

  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(backgroundColor: new Color(0xFF26C6DA)),
      body: new ListView(
        children: <Widget>[
          new Container(
            margin: new EdgeInsets.all(20.0),
            child: new FlutterLogo(size: 100.0, colors: Colors.blue),
          ),
          new Container(
            margin: new EdgeInsets.only(left: 16.0, right: 16.0),
            child: new Column(
              children: <Widget>[
                visibilityObs ? new Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    new Expanded(
                      flex: 11,
                      child: new TextField(
                        maxLines: 1,
                        style: Theme.of(context).textTheme.title,
                        decoration: new InputDecoration(
                          labelText: "Observation",
                          isDense: true
                        ),
                      ),
                    ),
                    new Expanded(
                      flex: 1,
                      child: new IconButton(
                        color: Colors.grey[400],
                        icon: const Icon(Icons.cancel, size: 22.0,),
                        onPressed: () {
                          _changed(false, "obs");
                        },
                      ),
                    ),
                  ],
                ) : new Container(),

                visibilityTag ? new Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    new Expanded(
                      flex: 11,
                      child: new TextField(
                        maxLines: 1,
                        style: Theme.of(context).textTheme.title,
                        decoration: new InputDecoration(
                          labelText: "Tags",
                          isDense: true
                        ),
                      ),
                    ),
                    new Expanded(
                      flex: 1,
                      child: new IconButton(
                        color: Colors.grey[400],
                        icon: const Icon(Icons.cancel, size: 22.0,),
                        onPressed: () {
                          _changed(false, "tag");
                        },
                      ),
                    ),
                  ],
                ) : new Container(),
              ],
            )
          ),
          new Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new InkWell(
                onTap: () {
                  visibilityObs ? null : _changed(true, "obs");
                },
                child: new Container(
                  margin: new EdgeInsets.only(top: 16.0),
                  child: new Column(
                    children: <Widget>[
                      new Icon(Icons.comment, color: visibilityObs ? Colors.grey[400] : Colors.grey[600]),
                      new Container(
                        margin: const EdgeInsets.only(top: 8.0),
                        child: new Text(
                          "Observation",
                          style: new TextStyle(
                            fontSize: 12.0,
                            fontWeight: FontWeight.w400,
                            color: visibilityObs ? Colors.grey[400] : Colors.grey[600],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
              new SizedBox(width: 24.0),
              new InkWell(
                onTap: () {
                  visibilityTag ? null : _changed(true, "tag");
                },
                child: new Container(
                  margin: new EdgeInsets.only(top: 16.0),
                  child: new Column(
                    children: <Widget>[
                      new Icon(Icons.local_offer, color: visibilityTag ? Colors.grey[400] : Colors.grey[600]),
                      new Container(
                        margin: const EdgeInsets.only(top: 8.0),
                        child: new Text(
                          "Tags",
                          style: new TextStyle(
                            fontSize: 12.0,
                            fontWeight: FontWeight.w400,
                            color: visibilityTag ? Colors.grey[400] : Colors.grey[600],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
            ],
          )                    
        ],
      )
    );
  }
}

6
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ นี่คือการใช้งาน "แสดง / ซ่อนวิดเจ็ตทางโปรแกรม" อย่างถูกต้อง
บิชวัจโยตีรอย

ใช่สิ่งนี้ควรได้รับการยอมรับอย่างแน่นอนเพราะสิ่งนี้ใช้เสาหลักของ Flutter เช่น setState () ... ไม่เช่นนั้นคุณจะกลับไปกลับมาระหว่าง Visible / InVisible ในวิดเจ็ต Stateful ของคุณอย่างไร!?
Yo Apps

31

ตอนนี้ Flutter มีวิดเจ็ตการมองเห็นที่คุณควรใช้เพื่อแสดง / ซ่อนวิดเจ็ต วิดเจ็ตยังสามารถใช้เพื่อสลับไปมาระหว่าง 2 วิดเจ็ตได้โดยการเปลี่ยนการแทนที่

วิดเจ็ตนี้สามารถบรรลุสถานะใด ๆ ที่มองเห็นได้มองไม่เห็นหายไปและอื่น ๆ อีกมากมาย

    Visibility(
      visible: true //Default is true,
      child: Text('Ndini uya uya'),
      //maintainSize: bool. When true this is equivalent to invisible;
      //replacement: Widget. Defaults to Sizedbox.shrink, 0x0
    ),

21

ลองใช้Offstageวิดเจ็ต

ถ้าแอตทริบิวต์offstage:trueไม่ใช้พื้นที่ทางกายภาพและมองไม่เห็น

หากแอตทริบิวต์offstage:falseจะครอบครองพื้นที่ทางกายภาพและมองเห็นได้

Offstage(
   offstage: true,
   child: Text("Visible"),
),

หมายเหตุเกี่ยวกับสิ่งนี้: สถานะเอกสาร Flutter "สามารถใช้ Offstage เพื่อวัดขนาดของวิดเจ็ตโดยไม่ต้องนำมาแสดงบนหน้าจอ (ยัง) หากต้องการซ่อนวิดเจ็ตจากมุมมองในขณะที่ไม่ต้องการให้ลบวิดเจ็ตออกจากโครงสร้างทั้งหมด แทนที่จะทำให้มันมีชีวิตอยู่ในทรีย่อยนอกเวที ".
lukeic

13

คุณสามารถห่อหุ้มวิดเจ็ตใด ๆ ในโค้ดของคุณด้วยวิดเจ็ตใหม่ที่เรียกว่า (การมองเห็น) ซึ่งมาจากหลอดไฟสีเหลืองที่ด้านซ้ายสุดของวิดเจ็ตที่คุณต้องการให้มองเห็นได้

ตัวอย่าง: บอกว่าคุณต้องการทำให้แถวมองไม่เห็น:

  1. คลิกในหลอดไฟและเลือก (ห่อด้วยวิดเจ็ต)
  2. เปลี่ยนชื่อวิดเจ็ตเป็น Visibility
  3. เพิ่มคุณสมบัติที่มองเห็นได้และตั้งค่าเป็นเท็จ
  4. ลูกของวิดเจ็ตที่สร้างขึ้นใหม่ (Visibility Widget) คือวิดเจ็ตที่คุณต้องการให้มองไม่เห็น

              Visibility(
                  visible: false,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      SizedBox(
                        width: 10,
                      ),
                      Text("Search",
                        style: TextStyle(fontSize: 20
                        ),),
                    ],
                  ),
                ),
    

ฉันหวังว่ามันจะช่วยใครบางคนในอนาคต


10
bool _visible = false;

 void _toggle() {
    setState(() {
      _visible = !_visible;
    });
  }

onPressed: _toggle,

Visibility(
            visible:_visible,
            child: new Container(
            child: new  Container(
              padding: EdgeInsets.fromLTRB(15.0, 0.0, 15.0, 10.0),
              child: new Material(
                elevation: 10.0,
                borderRadius: BorderRadius.circular(25.0),
                child: new ListTile(
                  leading: new Icon(Icons.search),
                  title: new TextField(
                    controller: controller,
                    decoration: new InputDecoration(
                        hintText: 'Search for brands and products', border: InputBorder.none,),
                    onChanged: onSearchTextChanged,
                  ),
                  trailing: new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
                    controller.clear();
                    onSearchTextChanged('');
                  },),
                ),
              ),
            ),
          ),
          ),

9

ในFlutter 1.5และDart 2.3สำหรับการมองเห็นหายไปคุณสามารถตั้งค่าการมองเห็นได้โดยใช้คำสั่ง if ภายในคอลเลกชันโดยไม่ต้องใช้คอนเทนเนอร์

เช่น

child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
              Text('This is text one'),
              if (_isVisible) Text('can be hidden or shown'), // no dummy container/ternary needed
              Text('This is another text'),
              RaisedButton(child: Text('show/hide'), onPressed: (){
                  setState(() {
                    _isVisible = !_isVisible; 
                  });
              },)

          ],
        )

นั่นเป็นสิ่งที่ดีกว่ามากจากนั้นตัวเลือกที่มีอยู่ในรุ่นก่อนหน้าของกระพือ / โผขอบคุณ!
Hammer

5

สำหรับผู้เริ่มต้นลองสิ่งนี้ด้วย

class Visibility extends StatefulWidget {
  @override
  _VisibilityState createState() => _VisibilityState();
}

class _VisibilityState extends State<Visibility> {
  bool a = true;
  String mText = "Press to hide";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Visibility",
      home: new Scaffold(
          body: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new RaisedButton(
                onPressed: _visibilitymethod, child: new Text(mText),),
                a == true ? new Container(
                width: 300.0,
                height: 300.0,
                color: Colors.red,
              ) : new Container(),
            ],
          )
      ),
    );
  }

  void _visibilitymethod() {
    setState(() {
      if (a) {
        a = false;
        mText = "Press to show";
      } else {
        a = true;
        mText = "Press to hide";
      }
    });
  }
}

5

อัปเดต

ตอนนี้ Flutter มีวิดเจ็ตVisibility ในการติดตั้งโซลูชันของคุณเองให้เริ่มต้นด้วยรหัสด้านล่าง


สร้างวิดเจ็ตด้วยตัวคุณเอง

แสดงซ่อน

class ShowWhen extends StatelessWidget {
  final Widget child;
  final bool condition;
  ShowWhen({this.child, this.condition});

  @override
  Widget build(BuildContext context) {
    return Opacity(opacity: this.condition ? 1.0 : 0.0, child: this.child);
  }
}

แสดง / ลบ

class RenderWhen extends StatelessWidget {
  final Widget child;
  final bool condition;
  RenderWhen({this.child, this.show});

  @override
  Widget build(BuildContext context) {
    return this.condition ? this.child : Container();
  }
}

ยังไงก็ตามใครมีชื่อที่ดีกว่าสำหรับวิดเจ็ตด้านบนหรือไม่?

อ่านเพิ่มเติม

  1. บทความเกี่ยวกับวิธีสร้างวิดเจ็ตการมองเห็น

3

ตามที่ @CopsOnRoad ไฮไลต์ไว้แล้วคุณสามารถใช้วิดเจ็ตการเปิดเผย แต่ถ้าคุณต้องการคงสถานะไว้เช่นหากคุณต้องการสร้าง viewpager และทำให้ปุ่มบางปุ่มปรากฏขึ้นและหายไปตามหน้าเว็บคุณสามารถทำได้ด้วยวิธีนี้

void checkVisibilityButton() {
  setState(() {
  isVisibileNextBtn = indexPage + 1 < pages.length;
  });
}    

 Stack(children: <Widget>[
      PageView.builder(
        itemCount: pages.length,
        onPageChanged: (index) {
          indexPage = index;
          checkVisibilityButton();
        },
        itemBuilder: (context, index) {
          return pages[index];
        },
        controller: controller,
      ),
      Container(
        alignment: Alignment.bottomCenter,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Visibility(
              visible: isVisibileNextBtn == true ? true : false,
              child: "your widget"
            )
          ],
        ),
      )
    ]))


-8

ทางออกหนึ่งคือการตั้งค่าคุณสมบัติสีของวิดเจ็ตมอกเป็น Colors.transparent ตัวอย่างเช่น:

IconButton(
    icon: Image.asset("myImage.png",
        color: Colors.transparent,
    ),
    onPressed: () {},
),

1
ไม่ใช่ทางออกที่ดีเนื่องจากโปร่งใสIconButtonยังคงได้รับการคลิกและใช้พื้นที่ โปรดแก้ไขหรือลบคำตอบนี้ก่อนที่จะมีคนลงคะแนน
CopsOnRoad
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.