프로그래밍 방식으로 Flutter에서 위젯 표시 / 숨기기


112

Android에서 모든 단일 View하위 클래스에는 객체 setVisibility()의 가시성을 수정할 수 있는 메서드가 있습니다.View

가시성을 설정하는 세 가지 옵션이 있습니다.

  • Visible : View레이아웃 내부에 보이는 것을 렌더링합니다.
  • 보이지 않음 :을 숨기지 View만 View표시되는 경우 차지하는 것과 동일한 간격을 남깁니다.
  • 사라짐 :을 숨기고 View레이아웃에서 완전히 제거합니다. 그건 마치 그 height와 width있었다0dp

Flutter의 위젯에 대해 위와 동일한 것이 있습니까?

빠른 참조 : https://developer.android.com/reference/android/view/View.html#attr_android:visibility

답변:


81

업데이트 :이 답변이 작성 되었으므로이 Visibility문제에 대한 최상의 솔루션을 제공했습니다.


당신은 사용할 수 있습니다 Opacity와 opacity:의 0.0요소가 숨겨져 있지만 여전히 공간을 차지하게 그립니다.

공간을 차지하지 않도록하려면 빈 Container().

편집 : Opacity 개체로 감싸려면 다음을 수행하십시오.

            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

3
위젯이 일반적으로 사용자 입력에 반응하는 경우 위젯도로 래핑해야 IgnorePointer합니다. 그렇지 않으면 사용자가 계속 트리거 할 수 있습니다.
— Duncan Jones

1
위젯이 여전히 있고 탭 등에 응답 할 수 있기 때문에 이상적이지 않습니다.이를 처리하는 가장 좋은 방법은 가시성 위젯을 사용하여 아래 답변을 참조하십시오.
— Russell Zornes

주석이 위쪽으로 말했듯이, 불투명도를 사용하면 renderTree에서 위젯이 렌더링되며 경우에 따라 원하는 것이 아닙니다. 가시성 위젯을 사용하는 것이 가장 좋습니다.
— Isac Moura

위젯을 보이지 않게 만들고 불투명도를 0으로하는 것은 두 가지 다른 것입니다. 보이지 않는 위젯을 사용하면 여전히 상호 작용할 수 있습니다. 가시성 위젯을 사용하면 필요할 때까지 위젯을 제거 할 수 있습니다.
— UndercoverCoder

173

Invisible : 위젯이 화면의 물리적 공간을 차지하지만 사용자에게는 보이지 않습니다.

사라짐 : 위젯이 물리적 공간을 차지하지 않고 완전히 사라졌습니다.


보이지 않는 예

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

16
'만약'조건은 완벽합니다!
— johnc

I love flutter ❤️
— nipunasudha

62

질문과 공동 작업하고 빈으로 바꾸는 예를 보여줍니다 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],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
            ],
          )                    
        ],
      )
    );
  }
}

5
이것은 받아 들여진 대답이어야합니다. 이것은 "프로그램 표시 / 숨기기 위젯 '의 올바른 구현
— Bishwajyoti 로이

예, 이것은 Flutter의 기초 기둥 즉 setState ()를 사용하기 때문에 확실히 받아 들여 져야합니다.
— Yo Apps

27

Flutter는 이제 가시성 위젯을 포함합니다 을 표시 / 숨기기 위해 사용해야 이 있습니다. 위젯을 사용하여 교체를 변경하여 두 위젯간에 전환 할 수도 있습니다.

이 위젯은 보이는 상태, 보이지 않는 상태, 사라진 상태 등을 달성 할 수 있습니다.

    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

Offstage위젯 사용해보기

속성 offstage:true이 물리적 공간을 차지하지 않고 보이지 않는 경우,

속성 offstage:false이면 물리적 공간을 차지하고 표시됩니다.

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

참고 : Flutter 문서 상태, "Offstage를 사용하여 위젯을 화면으로 가져 오지 않고도 (아직) 위젯의 크기를 측정 할 수 있습니다. 위젯이 필요하지 않은 동안보기에서 위젯을 숨기려면 트리에서 위젯을 완전히 제거하는 것이 좋습니다. Offstage 하위 트리에서 유지하는 것보다. "
— 미지근한

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

에서 플러터 1.5 및 다트 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; 
                  });
              },)

          ],
        )

이전 flutter / dart 버전에서 사용할 수있는 옵션보다 훨씬 낫습니다.
— Hammer

8

(Visibility)라는 새 위젯을 사용하여 코드의 모든 위젯을 캡슐화 할 수 있습니다. 이는 위젯의 맨 왼쪽에있는 노란색 램프에서 표시되지 않도록 할 수 있습니다.

예 : 행을 보이지 않게 만들고 싶다고 가정합니다.

  1. 램프를 클릭하고 (Wrap with widget)을 선택하십시오.
  2. 위젯 이름을 Visibility로 변경
  3. visible 속성을 추가하고 false로 설정합니다.
  4. 새로 생성 된 위젯 (Visibility Widget)의 자식은 보이지 않게하려는 위젯입니다.

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

앞으로 누군가를 도울 수 있기를 바랍니다.


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

3

최신 정보

이제 Flutter에 가시성 위젯이 있습니다. 자체 솔루션을 구현하려면 아래 코드로 시작하십시오.


직접 위젯을 만드세요.

표시 / 숨기기

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에서 이미 강조 표시했듯이 가시성 위젯을 사용할 수 있습니다. 그러나 상태를 유지하고 싶다면, 예를 들어 뷰 페이저를 구축하고 페이지를 기반으로 특정 버튼이 나타나고 사라지도록하려면 다음과 같이 할 수 있습니다.

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

한 가지 해결책은 tis 위젯 색상 속성을 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.