Search code examples
flutterdartflutter-layout

How to use ListView and stop element from scrolling?


I have a screen with a ListView that holds an SVG, Stack and TextFields. When the keyboard is opened, I get the usual Overflow error so I'm using a ListView to combat it since I'm using a Column anyway.

I want my SVG image to stay fixed at the top while the rest scrolls underneath it, anyway to give the image a fixed position?

child: Scaffold(
        body: SafeArea(
          child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 32.0),
              width: double.infinity,
              child: ListView(
                children: [
                  const SizedBox(
                    height: 50,
                  ),
                  SvgPicture.asset( //Should stay fixed while rest scroll
                    'assets/example.svg',
                    color: primaryColor,
                    height: 80.0,
                  ),
                  const SizedBox(height: 50),
                  Center(
                    child: Stack(
                      children: [
                        _image != null
                            ? InkWell(
                          onTap: selectImage,
                          child: CircleAvatar(
                            radius: 48,
                            backgroundImage: MemoryImage(_image!),
                          ),
                        )
                            : InkWell(
                          onTap: selectImage,
                          child: const CircleAvatar(
                            radius: 48,
                            backgroundImage: AssetImage('assets/user.png'),
                          ),
                        ),
                        Positioned(
                          bottom: -10,
                          left: 50,
                          child: IconButton(
                            onPressed: selectImage,
                            icon: const Icon(Icons.add_a_photo_outlined),
                          ),
                        ),
                      ],
                    ),
                  ),
                  const SizedBox(height: 50),
                  TextFieldInput(...),
                  TextFieldInput(...),
                  TextFieldInput(...),
                  TextFieldInput(...)...

I've tried taking the SVG out of the Column and changing the ListView into a Column with a SingleChildScrollView parent and I still get Render Overflow. Code follows:

child: Scaffold(
    body: SafeArea(
      child: Column(
        children: [
          SvgPicture.asset(
            'assets/example.svg',
            color: primaryColor,
            height: 80.0,
          ),
          SingleChildScrollView(
            child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 32.0),
                width: double.infinity,
                child: Column(
                  children: [
                    const SizedBox(height: 50),
                    Center(
                      child: Stack(
                        children: [
                          _image != null
                              ? InkWell(
                                  onTap: selectImage,
                                  child: CircleAvatar(
                                    radius: 48,
                                    backgroundImage: MemoryImage(_image!),
                                  ),
                                )
                              : InkWell(
                                  onTap: selectImage,
                                  child: const CircleAvatar(
                                    radius: 48,
                                    backgroundImage:
                                        AssetImage('assets/user.png'),
                                  ),
                                ),
                          Positioned(
                            bottom: -10,
                            left: 50,
                            child: IconButton(
                              onPressed: selectImage,
                              icon: const Icon(Icons.add_a_photo_outlined),
                            ),
                          ),
                        ],
                      ),
                    ),
                    const SizedBox(height: 50),
                    TextFieldInput(..),
                    TextFieldInput(..),
                    TextFieldInput(..)...

What would be the correct approach to this?


Solution

  • Wrap your SingleChildScrollView in a Expanded widget, like this:

    child: Scaffold(
        body: SafeArea(
          child: Column(
            children: [
              SvgPicture.asset(
                'assets/example.svg',
                color: primaryColor,
                height: 80.0,
              ),
              Expanded( //<--- add this
               child: SingleChildScrollView(
                child: Container(
                    padding: const EdgeInsets.symmetric(horizontal: 32.0),
                    width: double.infinity,
                    child: Column(
                      children: [
                        const SizedBox(height: 50),
                        Center(
                          child: Stack(
                            children: [
                              _image != null
                                  ? InkWell(
                                      onTap: selectImage,
                                      child: CircleAvatar(
                                        radius: 48,
                                        backgroundImage: MemoryImage(_image!),
                                      ),
                                    )
                                  : InkWell(
                                      onTap: selectImage,
                                      child: const CircleAvatar(
                                        radius: 48,
                                        backgroundImage:
                                            AssetImage('assets/user.png'),
                                      ),
                                    ),
                              Positioned(
                                bottom: -10,
                                left: 50,
                                child: IconButton(
                                  onPressed: selectImage,
                                  icon: const Icon(Icons.add_a_photo_outlined),
                                ),
                              ),
                            ],
                          ),
                        ),
                        const SizedBox(height: 50),
                        TextFieldInput(..),
                        TextFieldInput(..),
                        TextFieldInput(..)...