Flutter : Sliverappbar sketch scroll

Issue

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

  • image now overlap under leading and action icons
  • due to expandedHeight , different ratio of image might get cut
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),
    );
  }
}

Answered By – Chris Wickens

Answer Checked By – Clifford M. (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *