fluttercommunity/flutter_sticky_headers

[BUG] Jumpy header inside CustomScrollView with center key

Areopagitics opened this issue · 9 comments

When using StickyHeader inside a CustomScrollView with center key, the header immediately before the center header month jumps around; all the other header months have no problems. A plug and play ready example is found below. If there is an easy way to fix the problem, it would be much appreciated. I have tried countless other options...I am really surprised the sticky header is not included with the flutter CustomScrollView widgets.

Peek 2022-10-22 13-18

import 'package:flutter/material.dart';
import 'package:sticky_headers/sticky_headers.dart';

Map _months = {
  1:'January',
  2:'February',
  3:'March',
  4:'April',
  5:'May',
  6:'June',
  7:'July',
  8:'August',
  9:'September',
  10:'October',
  11:'November',
  12:'December',
};

abstract class BasePage extends StatefulWidget {
  BasePage({Key? key}) : super(key: key);
}

abstract class BaseState<Page extends BasePage> extends State<Page> {
  String screenName();
}
class CalendarPage extends BasePage {
  CalendarPage({Key? key}) : super(key: key);
  @override
  _CalendarPageState createState() => _CalendarPageState();
}


class _CalendarPageState extends BaseState<CalendarPage>{
  _CalendarPageState();


  Key centerKey = ValueKey<String>('center');
  var date = DateTime.now();


 Widget monthBuilder (BuildContext context, int plusMinus){
    int count = (date.month - 13) * -1;
    if(plusMinus==-1){count=date.month-1;}
    return SliverList(
      key: plusMinus==1 ? centerKey:null,
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          int month=date.month+index;
          if(plusMinus==-1){month=date.month-1+(-1*index);}
          return StickyHeader(
            header: Container(
              color: Colors.brown,
              padding: EdgeInsets.symmetric(vertical: 12.0),
              alignment: Alignment.center,
              child: Text('${_months[month]}',
                style: Theme.of(context).textTheme.headline2,
              ),
            ),
            content: ListView.builder(
              shrinkWrap: true,
              itemCount: DateTime(date.year,month+1,0).day,//check last day of month for days,
              itemBuilder: (context, int index) {
                return Column(children: [
                  Divider(),
                  TextButton( onPressed: () {  },
                  child: Text('Data'),),
                ]);
              },
            ),
          );
        },
        childCount: count,
      )
    );
  }

  @override
  String screenName() => "Calendar ${date.year}";

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
        center: centerKey,
        slivers: [
          monthBuilder(context, -1),
          monthBuilder(context, 1),
        ],
      );
  }
}

Yes this also happens for me, but only for a the first bit of the child, and gets fixed after one whole screen has been scrolled.

The way this library works is very hacky, the only work around is to calculate the header position during paint as done in the PR above. A better solution would be using flutter_sticky_header, except that the sticky headers above the center key are at the bottom instead of top.

I'm seeing a related issue where if I add an item to the list or scroll view that the header can jump down the list (by the amount the list size has increased) until a scroll is initiated, upon which it resets correctly. It's an edge case to be sure but can look bad to end users.

Can you checkout if my fork (#72) fixes that issue?

Can you checkout if my fork (#72) fixes that issue?

Since the fork was merged, it unfortunately doesn't. I just tested with the code above. The same problem happens.

WDYM? The code in the issue should be fixed in my fork, as I use that fork for a production app where it works. It is also not merged yet. How are you importing the code?

My bad ... I thought it was merged already.

BTW. I'm already looking to SliverMainAxisGroup, which will provide Sticky Headers out of the box in flutter.

This shoudl probably stay open, but thanks for pointing that out! Then we can also finally move away from this library