Tampilkan / sembunyikan widget di Flutter secara terprogram


116

Di Android, setiap Viewsubclass memiliki setVisibility()metode yang memungkinkan Anda mengubah visibilitas suatu Viewobjek

Ada 3 pilihan pengaturan visibilitas:

  • Visible: Menampilkan yang Viewterlihat di dalam tata letak
  • Tak terlihat: Menyembunyikan View, tetapi meninggalkan celah yang setara dengan apa yang Viewakan ditempati jika terlihat
  • Hilang: Menyembunyikan View, dan menghapus seluruhnya dari tata letak. Seolah-olah itu heightdan widthdulu0dp

Apakah ada sesuatu yang setara di atas untuk Widget di Flutter?

Untuk referensi cepat: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

Jawaban:


82

UPDATE: Sejak jawaban ini ditulis, Visibilitydiperkenalkan dan memberikan solusi terbaik untuk masalah ini.


Anda dapat menggunakan Opacitydengan opacity:dari 0.0untuk menarik membuat elemen tersembunyi namun masih menempati ruang.

Agar tidak menempati ruang, gantilah dengan yang kosong Container().

EDIT: Untuk membungkusnya dalam objek Opacity, lakukan hal berikut:

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

Tutorial singkat Pengembang Google tentang Opacity: https://youtu.be/9hltevOHQBw


3
Terima kasih! Ya, itu bukan cara terbersih untuk melakukannya, tapi pasti akan mencapai tujuannya. Adakah peluang untuk memiliki fungsionalitas visibilitas yang terintegrasi dengan widget di masa mendatang?
pengguna3217522

3
Jika widget biasanya bereaksi terhadap masukan pengguna, pastikan untuk menggabungkannya IgnorePointerjuga, jika tidak, pengguna masih dapat memicunya.
Duncan Jones

1
Ini tidak ideal karena widget masih ada dan dapat merespon ketukan dll. Lihat jawaban di bawah ini menggunakan widget Visibility untuk cara terbaik menangani ini.
Russell Zornes

Seperti yang dikatakan oleh komentar ke atas, menggunakan opacity akan membuat Widget di renderTree, dengan dalam beberapa kasus bukanlah yang Anda inginkan. Menggunakan widget visibilitas paling disarankan.
Isac Moura

Membuat widget tidak terlihat dan memiliki opasitas sebagai0 adalah dua hal yang berbeda. Dengan widget yang tidak terlihat, Anda masih dapat berinteraksi dengannya, hanya saja tidak terlihat. Widget visibilitas memungkinkan Anda menghapus widget hingga diperlukan.
UndercoverCoder

176

Tak terlihat : Widget mengambil ruang fisik di layar tetapi tidak terlihat oleh pengguna.

Hilang : Widget tidak memakan ruang fisik apa pun dan benar-benar hilang.


Contoh tak terlihat

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

Hilang contoh

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

Sebagai alternatif, Anda dapat menggunakan ifkondisi untuk yang tidak terlihat dan hilang.

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

17
Kondisi 'jika' itu sempurna!
johnc

Saya suka flutter ❤️
nipunasudha

62

Untuk berkolaborasi dengan pertanyaan dan menunjukkan contoh menggantinya dengan yang kosong Container().

Berikut contohnya di bawah ini:

masukkan deskripsi gambar di sini

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

5
Ini harus menjadi jawaban yang diterima. Ini adalah implementasi yang benar dari "tampilkan / sembunyikan widget secara terprogram"
Bishwajyoti Roy

Ya, ini pasti harus diterima karena ini menggunakan pilar dasar Flutter yaitu setState () ... jika tidak, bagaimana lagi Anda akan bolak-balik antara Terlihat / Tidak Terlihat di widget Stateful Anda!?.
Yo Apps

27

Flutter sekarang berisi Widget Visibilitas yang harus Anda gunakan untuk menampilkan / menyembunyikan widget. Widget juga dapat digunakan untuk beralih di antara 2 widget dengan mengganti penggantinya.

Widget ini dapat mencapai salah satu status terlihat, tidak terlihat, hilang, dan banyak lagi.

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

19

Coba Offstagewidgetnya

Jika atribut offstage:truetidak menempati ruang fisik dan tidak terlihat,

Jika atribut offstage:falseitu akan menempati ruang fisik dan terlihat

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

Perhatikan ini: dokumen Flutter menyatakan, "Offstage dapat digunakan untuk mengukur dimensi widget tanpa membawanya ke layar (belum). Untuk menyembunyikan widget dari tampilan saat tidak diperlukan, lebih baik menghapus widget dari pohon sepenuhnya daripada menjaganya tetap hidup di subpohon Offstage. ".
Lukeic

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

Di flutter 1.5 dan Dart 2.3 untuk visibilitas hilang, Anda dapat menyetel visibilitas dengan menggunakan pernyataan if dalam koleksi tanpa harus menggunakan container.

misalnya

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

          ],
        )

Itu jauh lebih baik daripada opsi yang tersedia di versi flutter / dart sebelumnya.
Palu

8

Anda dapat merangkum widget apa pun dalam kode Anda dengan widget baru yang disebut (Visibilitas), ini dari lampu kuning di sisi paling kiri widget yang Anda inginkan agar tidak terlihat

contoh: katakanlah Anda ingin membuat baris tidak terlihat:

  1. Klik di lampu dan pilih (Bungkus dengan widget)
  2. Ubah nama widget menjadi Visibilitas
  3. Tambahkan properti visible dan setel ke false
  4. Anak dari widget yang baru dibuat (Visibility Widget) adalah Widget yang Anda inginkan agar tidak terlihat

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

Saya berharap ini akan membantu seseorang di masa depan


5

Untuk pemula coba ini juga.

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

3

Memperbarui

Flutter sekarang memiliki widget Visibilitas . Untuk menerapkan solusi Anda sendiri, mulailah dengan kode di bawah ini.


Buat widget sendiri.

tunjukan Sembunyikan

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

tampilkan / hapus

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

Ngomong-ngomong, apakah ada yang punya nama yang lebih baik untuk widget di atas?


Lebih Banyak Bacaan

  1. Artikel tentang cara membuat widget visibilitas.

3

Seperti yang telah disorot oleh @CopsOnRoad, Anda dapat menggunakan widget Visibility. Tetapi, jika Anda ingin mempertahankan statusnya, misalnya, jika Anda ingin membuat viewpager dan membuat tombol tertentu muncul dan menghilang berdasarkan halaman, Anda dapat melakukannya dengan cara ini

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"
            )
          ],
        ),
      )
    ]))

0

Mungkin Anda bisa menggunakan fungsi Navigator seperti ini Navigator.of(context).pop();


-8

Salah satu solusinya adalah menyetel properti warna widget ini ke Colors.transparent. Misalnya:

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

1
Bukan solusi yang baik karena transparan IconButtonmasih menerima klik dan menempati ruang. Mohon edit atau hapus jawaban ini sebelum orang-orang memberikan suara negatif.
CopsOnRoad
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.