1

I have a problem with a SizeTransition that is within a SliverFillRemaining. The issue is that the SliverFillRemaining does not adjust its size proportionally to the height of the SizeTransition. Even when the sizeFactor of the SizeTransition is 0, the SliverFillRemaining still occupies the space it would when the SizeTransition's sizeFactor is 1. I expected SliverFillRemaining to only fill the remaining space in the viewport but in the sample code below it uses more space than necessary. This is not an issue with SingleChildScrollView for which I've provided sample code as well.

Image showing error

Code with SliverFillRemaining showing too much space being taken up:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: const CustomScrollView(
          slivers: [
            SliverFillRemaining(
              hasScrollBody: false,
              child: Column(
                children: [
                  SizeTransitionExample(),
                  SizeTransitionExample(),
                  SizeTransitionExample(),
                  SafeArea(child: Text("Text")),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class SizeTransitionExample extends StatefulWidget {
  const SizeTransitionExample({super.key});

  @override
  State<SizeTransitionExample> createState() => _SizeTransitionExampleState();
}

class _SizeTransitionExampleState extends State<SizeTransitionExample> with TickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 3),
    vsync: this,
  )..repeat(reverse: true);
  late final Animation<double> _animation = CurvedAnimation(
    parent: _controller,
    curve: Curves.fastOutSlowIn,
  );

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final pageHeight = MediaQuery.sizeOf(context).height;

    return SizeTransition(
      sizeFactor: _animation,
      child: Center(
        child: FlutterLogo(size: pageHeight / 3),
      ),
    );
  }
}

Code with SingleChildScrollView with the expected behavior:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: const SingleChildScrollView(
          child: ColoredBox(
            color: Colors.amber,
            child: Column(
              children: [
                SizeTransitionExample(),
                SizeTransitionExample(),
                SizeTransitionExample(),
                SafeArea(child: Text("Text")),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class SizeTransitionExample extends StatefulWidget {
  const SizeTransitionExample({super.key});

  @override
  State<SizeTransitionExample> createState() => _SizeTransitionExampleState();
}

class _SizeTransitionExampleState extends State<SizeTransitionExample> with TickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 3),
    vsync: this,
  )..repeat(reverse: true);
  late final Animation<double> _animation = CurvedAnimation(
    parent: _controller,
    curve: Curves.fastOutSlowIn,
  );

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final pageHeight = MediaQuery.sizeOf(context).height;

    return SizeTransition(
      sizeFactor: _animation,
      child: Center(
        child: FlutterLogo(size: pageHeight / 3),
      ),
    );
  }
}
Petri
  • 1,020
  • 3
  • 14
  • 24

0 Answers0