본문 바로가기

개발하자

Float로 고정 바닥글로 스크롤 보기를 만드는 방법은 무엇입니까?

반응형

Float로 고정 바닥글로 스크롤 보기를 만드는 방법은 무엇입니까?

화면 크기에 관계없이 스크롤 보기(예: )와 바닥글이 있는 보기를 만들고 싶습니다. 화면이 충분히 크면 스크롤과 바닥글 사이의 빈 공간을 사용하고, 그렇지 않으면 확장되어 바닥글 위의 위젯만 스크롤할 수 있습니다.

키보드가 바닥글을 넘치게 하고 제자리에 유지되도록 하는 것과 비슷하지만 차이점이 있습니다.

비슷한 것

example

return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          SingleChildScrollView(
            child: Padding(
              padding: const EdgeInsets.only(left: 30.0, right: 30.0, top: 80.0),
              child: Form(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                   // Multiple widgets and form fields
                  ],
                ),
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 50.0),
            child: SafeArea(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  // Footer widgets
                ],
              ),
            ),
          )
        ],
      ),
    );



어려운 점은 하나는 제약이 필요하고 다른 하나는 제약을 제거하기 때문에 함께 일하는 것이 어렵다는 것이다.

요령은 a를 사용하여 직접 계산하는 것입니다. 에 의해 키보드 크기를 얻음으로써 바닥글이 사라지고 콘텐츠에 더 많은 공간이 남을 수 있습니다.

다음은 재사용 가능한 위젯입니다:

class FooterLayout extends StatelessWidget {
  const FooterLayout({
    Key key,
    @required this.body,
    @required this.footer,
  }) : super(key: key);

  final Container body;
  final Container footer;

  @override
  Widget build(BuildContext context) {
    return CustomMultiChildLayout(
      delegate: _FooterLayoutDelegate(MediaQuery.of(context).viewInsets),
      children: <Widget>[
        LayoutId(
          id: _FooterLayout.body,
          child: body,
        ),
        LayoutId(
          id: _FooterLayout.footer,
          child: footer,
        ),
      ],
    );
  }
}

enum _FooterLayout {
  footer,
  body,
}

class _FooterLayoutDelegate extends MultiChildLayoutDelegate {
  final EdgeInsets viewInsets;

  _FooterLayoutDelegate(this.viewInsets);

  @override
  void performLayout(Size size) {
    size = Size(size.width, size.height + viewInsets.bottom);
    final footer =
        layoutChild(_FooterLayout.footer, BoxConstraints.loose(size));

    final bodyConstraints = BoxConstraints.tightFor(
      height: size.height - max(footer.height, viewInsets.bottom),
      width: size.width,
    );

    final body = layoutChild(_FooterLayout.body, bodyConstraints);

    positionChild(_FooterLayout.body, Offset.zero);
    positionChild(_FooterLayout.footer, Offset(0, body.height));
  }

  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}

다음과 같이 사용:

FooterLayout(
  body: body,
  footer: footer,
),



Rémi의 대답이 맞긴 하지만, 와 를 결합하는 것만으로 원하는 것을 달성할 수 있는 더 쉬운 방법을 찾았습니다.

class ScrollableFooter extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
      return SingleChildScrollView(
        child: ConstrainedBox(
          constraints: constraints.copyWith(
            minHeight: constraints.maxHeight,
            maxHeight: double.infinity,
          ),
          child: IntrinsicHeight(
            child: Column(
              children: <Widget>[
               // Your body widgets here
                Expanded(
                  child: Align(
                    alignment: Alignment.bottomCenter,
                    child: // Your footer widget
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    });
  }
}



내가 이것을 해결한 방법은 고정과 가 위젯에 포장된 후에 그에 맞게 정렬하는 것이었다.


class ScrollableFooter extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        SingleChildScrollView(
          child: Container(
            padding: EdgeInsets.all(5),
            child: Column(
              children: <Widget>[
                // Your body widgets here
              ],
            ),
          ),
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: // Your fixed Footer here,
        ),
      ],
    );
  }
}




수용된 답변이 모바일 기기에서 작동하는 것처럼 보이지만, 폭이 높이보다 (훨씬) 클 때 문제가 발생한다. 이 경우 와 같은 역할을 하며 높이가 증가하여 바닥글이 화면 밖으로 밀려나 있습니다.

내부 작동의 정의에 문제가 있다고 생각합니다:

... 대신 좀 더 합리적인 높이로 크기를 조정합니다.

나는 @Remi의 해결책이 그러한 경우에도 효과가 있다는 것을 확인할 수 있다.

Flutter 프레임워크에서 제공하는 표준 위젯이 될 만하다.




간단한 방법으로 구현하고자 하는 사용자에게 다음 코드가 도움이 될 수 있습니다:

Scaffold(
      appBar: buildAppBar('Some cool appbar'),
      body: Column(
        children: [
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  PackageCard(),
                  PackageCard(),
                  PackageCard(),
                ],
              ),
            ),
          ),
          Container(
            child: Text('Your super cool Footer'),
            color: Colors.amber,
          )
        ],
      ),
    );

시각적 표현:-

---Column
    |
    |---Expanded--
                 |-SingleChildScrollView (column /YOUR SCROLLABLE VIEW)
    |
    |-Container(YOUR FOOTER)

여기서 같이 썼어요




허용된 솔루션은 많은 경우에 작동하지만 ListView와 같은 것을 사용하려는 경우에는 고유한 높이를 제공할 수 없기 때문에 까다로워집니다. 저는 다른 해결책을 찾으려고 노력했고, 제가 할 수 있다는 것이 밝혀졌고, 그것은 더 유연해 보입니다. 나는 은발로 이 상황을 해결할 수 있었다. 내용이 작은 조각 안에 있고 바닥글도 작은 조각 안에 있습니다.

팁: 은박지에 관한 모든 것인 "지루한 플룻 개발 쇼, 12화"를 보세요.

return Scaffold(
  body: CustomScrollView(
    shrinkWrap: true,
    slivers: [
      SliverToBoxAdapter(
        child: Column(
          children: [
            //content widgets
          ],
        ),
      ),
      SliverFillRemaining(
        hasScrollBody: false,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            //footer widgets,
          ],
        ),
      ),
    ],
  ),
);



스크롤 가능한 화면이 있는 바닥글을 만들려면 목록 보기와 함께 스택 위젯을 사용할 수 있습니다.Builder 및 SingleChildScrollview를 다음과 같이 표시합니다:

    Scaffold(
      body:Stack(
        alignment: Alignment.bottomCenter, 
        children: [
          ListView.builder(
            itemCount: 1,
            itemBuilder: (context, index) => SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Container( // Scrollable contents here
                color: Colors.red,
                height: 3000,
                width: 1000,
              ),
            ),
          ),
          Container( // Footer
            height:50,
            color:Colors.blue[900],
            width:MediaQuery.of(context).size.width,
            child:Center(child:Text("Footer")),
          ),
        ],
      ),
    );

반응형