flutterflutter-layoutsliverappbar

Flutter : Sliverappbar sketch scroll


I trying to create same UI/UX like this, image resize fit to appbar while scrolling, I have try using SliverAppBar and put image widget into title.

enter image description here

Facing issue

SliverAppBar(
  backgroundColor: Colors.black,
  leading: BackIcon()
  expandedHeight: context.mediaQuerySize.width,
  floating: false,
  pinned: true,
  snap: false,
  stretch: true,
  flexibleSpace: FlexibleSpaceBar(
    centerTitle: true,
    stretchModes: [StretchMode.fadeTitle],
    title: Container(
      margin: EdgeInsets.only(left: 15, right: 15),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(10),
        child: CachedNetworkImage(
          imageUrl: imagePath,
          fit: BoxFit.cover,
        ),
      ),
    ),
  ),
  actions: [
    ShareIcon()
  ],
),

Solution

  • You could try influencing the size/positioning of the image or button padding with the CustomScrollView's scrollController.offset value. For example: https://i.imgur.com/T8Sq4vS.gifv

    import 'dart:math';
    import 'package:flutter/material.dart';
    
    class CollapsingAvatarPage extends StatefulWidget {
      const CollapsingAvatarPage({Key? key}) : super(key: key);
    
      @override
      State<CollapsingAvatarPage> createState() => _CollapsingAvatarPageState();
    }
    
    class _CollapsingAvatarPageState extends State<CollapsingAvatarPage> {
      ScrollController scrollController = ScrollController();
    
      @override
      void initState() {
        super.initState();
        scrollController.addListener(() {
          setState(() {});
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return CustomScrollView(
          controller: scrollController,
          slivers: [
            SliverAppBar(
              backgroundColor: Colors.black,
              leading: const Icon(Icons.arrow_back),
              actions: const [
                ActionIcon(iconData: Icons.share),
                ActionIcon(iconData: Icons.flag),
              ],
              pinned: true,
              stretch: true,
              collapsedHeight: 80,
              expandedHeight: MediaQuery.of(context).size.height * 0.55,
              flexibleSpace: FlexibleSpaceBar(
                background: Container(
                  decoration: const BoxDecoration(
                    gradient: LinearGradient(
                      colors: [Colors.white60, Colors.black],
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                    ),
                  ),
                ),
                title: Container(
                  width: max(
                    100,
                    280 -
                        (scrollController.hasClients
                            ? scrollController.offset * 0.4
                            : 0),
                  ),
                  padding: const EdgeInsets.only(
                    left: 15,
                    right: 15,
                    top: 15,
                  ),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(10),
                    child: const FittedBox(
                      fit: BoxFit.fitHeight,
                      child: Image(
                        image: AssetImage('image.png'),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) => const Placeholder(),
                childCount: 100,
              ),
            )
          ],
        );
      }
    }
    
    class ActionIcon extends StatelessWidget {
      const ActionIcon({
        Key? key,
        required this.iconData,
      }) : super(key: key);
    
      final IconData iconData;
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Icon(iconData),
        );
      }
    }